如何使用XSL在XML转换中查找随机元素

如何使用XSL在XML转换中查找随机元素,xml,xslt,xhtml,transform,Xml,Xslt,Xhtml,Transform,我在转换XML时遇到了一个问题,就像我无法按正确的顺序获取元素一样。这些元素是随机的,无法预测它们出现的顺序 这是我的XML <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="test.xsl"?> <toc> <layout> <header>Item 1</header> &l

我在转换XML时遇到了一个问题,就像我无法按正确的顺序获取元素一样。这些元素是随机的,无法预测它们出现的顺序

这是我的XML

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<toc>
    <layout>
        <header>Item 1</header>
        <tocItem>item one - a</tocItem>
        <tocItem>item one - b</tocItem>
        <header>Item 2</header>
        <tocItem>item two - a</tocItem>
        <tocItem>item two - b</tocItem>
        <tocItem>item two - c</tocItem>
        <tocItem>item two - d</tocItem>
        <tocItem>item two - e</tocItem>
        <header>Item 3</header>
        <tocItem>item three - a</tocItem>
        <header>Item 4</header>
        <tocItem>item four - a</tocItem>
        <tocItem>item four - b</tocItem>
        <tocItem>item four - c</tocItem>
        <header>Item 5</header>
        <tocItem>item five - a</tocItem>
        <tocItem>item five - b</tocItem>
    </layout>
    <layout>
        <header>Item 1</header>
        <tocItem>item one - a</tocItem>
        <tocItem>item one - b</tocItem>
        <header>Item 2</header>
        <tocItem>item two - a</tocItem>  
    </layout>
    <layout>
        <header>Item 1</header>
        <tocItem>item one - a</tocItem>
        <tocItem>item one - b</tocItem>
        <tocItem>item one - c</tocItem>
        <tocItem>item one - d</tocItem>
        <tocItem>item one - e</tocItem>
        <header>Item 2</header>
        <tocItem>item two - c</tocItem>
        <tocItem>item two - d</tocItem>
        <tocItem>item two - e</tocItem>
        <header>Item 4</header>
        <tocItem>item four - a</tocItem>
        <tocItem>item four - b</tocItem>
        <header>Item 5</header>
        <tocItem>item five - a</tocItem>  
    </layout>
</toc>

项目1
项目1-a
项目一-b
项目2
项目2-a
项目2-b
项目2-c
项目2-d
项目二-e
项目3
项目3-a
项目4
项目4-a
项目4-b
项目4-c
项目5
项目5-a
项目5-b
项目1
项目1-a
项目一-b
项目2
项目2-a
项目1
项目1-a
项目一-b
项目一-c
项目1-d
项目一-e
项目2
项目2-c
项目2-d
项目二-e
项目4
项目4-a
项目4-b
项目5
项目5-a
这里是XSL

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/">

            <html lang="en">
            <head>
                <meta charset="UTF-8" />
                <title>Title</title>
            </head>

            <body>
                <div class="toc">
                    <xsl:for-each select="/toc/layout">
                    <div class="layout">                    
                        <xsl:for-each select="/toc/layout/header">
                            <div class="header">
                                <p><xsl:value-of select="header" /></p>
                            </div>
                        </xsl:for-each>
                        <xsl:for-each select="/toc/layout/tocItem">
                            <div class="tocItem">
                                <p><xsl:value-of select="tocItem" /></p>
                            </div>
                        </xsl:for-each>                    
                    </div>  
                    </xsl:for-each>              
                </div>
            </body>

            </html>
    </xsl:template>
 </xsl:stylesheet>

标题

当我尝试上述方法时,它只是重复第一个header元素和第一个tocItems。在layout div中尝试此代码时,我得到了所有元素。我的目标是按顺序逐个获取它们。如下图所示

项目1

项目1-a

项目一-b

项目2

项目2-a

项目2-b


第二项-c

我没有检查您试图实现的目标,但是您的
xsl:for each
显然是错误的。当您编写
时,for each中的上下文节点是一个
元素,我们希望进一步的选择是相对于该元素的,而不是来自文档根的绝对路径。我不明白为什么一开始你对每个都有两个级别的
xsl:for-each

我没有检查你想要实现什么,但是你的
xsl:for-each
显然是错误的。当您编写
时,for each中的上下文节点是一个
元素,我们希望进一步的选择是相对于该元素的,而不是来自文档根的绝对路径。我不明白为什么一开始每个都有两个级别的
xsl:foreach

一般来说,如果您只想使用基于元素名称的
class
属性将所有这些元素转换为HTML
div
,那么一个模板就足够了:

  <xsl:template match="toc | layout | header | tocItem">
      <div class="{local-name()}">
          <xsl:apply-templates/>
      </div>
  </xsl:template>
它使用XSLT 3 only声明
将标识转换设置为默认处理,但在早期版本中,您只需将其拼写为

<xsl:template match="@* | node()">
  <xsl:copy>
     <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>


请参阅联机试用。

一般来说,如果您只想使用基于元素名称的
属性将所有这些元素转换为HTML
div
,那么一个模板就足够了:

  <xsl:template match="toc | layout | header | tocItem">
      <div class="{local-name()}">
          <xsl:apply-templates/>
      </div>
  </xsl:template>
它使用XSLT 3 only声明
将标识转换设置为默认处理,但在早期版本中,您只需将其拼写为

<xsl:template match="@* | node()">
  <xsl:copy>
     <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>


请参阅联机试用。

我不明白您在这里想要实现什么。输入的顺序似乎非常精确。请在给定的示例中显示准确和完整的预期结果,并解释为获得该结果需要应用的逻辑。您在
中有
。这没有任何意义。一般来说,如果您只想根据元素名称使用
class
属性将所有这些元素转换为HTML
div
,那么一个模板就足够了;为了保持输入顺序,最好或者至少最简单的方法是简单地应用模板。有关示例,请参见。但是,我不确定您是否还希望将项目包装在标题后面或嵌套它们,那么可能需要更多的工作。@michael.hor257k,很抱歉,这是我的错误。我刚刚做了一个编辑。虽然我没有那么多编程技能,只是通过学习w3学校的XML教程来完成。@MartinHonnen,这正是我想要实现的,谢谢你。我不明白你在这里想要实现什么。输入的顺序似乎非常精确。请在给定的示例中显示准确和完整的预期结果,并解释为获得该结果需要应用的逻辑。您在
中有
。这没有任何意义。一般来说,如果您只想根据元素名称使用
class
属性将所有这些元素转换为HTML
div
,那么一个模板就足够了;为了保持输入顺序,最好或者至少最简单的方法是简单地应用模板。有关示例,请参见。但是,我不确定您是否还希望将项目包装在标题后面或嵌套它们,那么可能需要更多的工作。@michael.hor257k,很抱歉,这是我的错误。我刚刚做了一个编辑。虽然我没有太多的编程技能,只是通过学习w3学校的XML教程来完成。@MartinHonnen,这正是我想要实现的目标,谢谢你。这是我自己的一个错误。马丁·霍宁的小提琴似乎帮助了我。顺便说一句,谢谢你回答这个问题。那是我这边的一个错误。马丁·霍宁的小提琴似乎帮助了我。顺便说一句,谢谢你回答这个问题。