XSL Embedded for-each

时间:2011-08-18 18:29:08

标签: xml xslt loops foreach nested

我知道这里有一些内容,但我是XSLT的新手,我正在尝试在输入XML中位于不同位置但在同一节点级别的节点上执行嵌套for-each循环。

所以...例如:

    <Level1>
    <Level2>
        <Level3a>
          <Item1>Clothes Washed</Item1>
          <Item2>08/02/2011 06:54</Item2>
          <DoneBy>Ingrid</DoneBy>
        </Level3a>
        <Level3a>
          <Item1>Car Washed</Item1>
          <Item2>08/02/2011 08:25</Item2>
          <DoneBy>Jeanette</DoneBy>
        </Level3a>
        <Level3a>
          <Item1>Dog Walked</Item1>
          <Item2>08/02/2011 10:30</Item2>
          <DoneBy>Ingrid</DoneBy>
        </Level3a>
        <Level3b>
          <DoneWho>Ingrid</DoneWho>
          <JobTitle>Main Asst</JobTitle>
        </Level3b>
        <Level3b>
          <DoneWho>Jeanette</DoneWho>
          <JonTitle>2nd Asst</JobTitle>
        </Level3b>
      </Level2>
    </Level1>

我需要输出

    <Jobs>
      <CompletedJob>
        <JobTitle>Main Asst</JobTitle>
        <Job>Clothes Washed</Job>
        <CompOn>08/02/2011</CompOn>
        <CompAt>06:54<CompAt>
      </CompletedJob>
      <CompletedJob>
        <JobTitle>Main Asst</JobTitle>
        <Job>Dog Walked</Job>
        <CompOn>08/02/2011</CompOn>
        <CompAt>10:30</CompAt>
      </CompletedJob>
      <CompletedJob>
        <JobTitle>2nd Asst</JobTitle>
        <Job>Car Washed</Job>
        <CompOn>08/02/2011</CompOn>
        <CompAt>08:25</CompAt>
      </CompletedJob>
    </Jobs>
编辑:请看上面输出中的变化......我想这正是我想要做的。 用...取代输出再次感谢。

我已尝试过每个循环的neste,但我不能在主for-each循环内引用不同的节点。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:1)

不需要嵌套循环 - XSLT本质上是递归的。

以下样式表完成工作:

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

    <xsl:output method="xml"/>
    <xsl:template match="/">
        <Jobs>
            <xsl:for-each select="*/*/Level3a">
                <xsl:sort select="DoneBy"/>

                <CompletedJob>
                    <JobTitle>
                        <xsl:value-of select="../Level3b[DoneWho=current()/DoneBy]/JobTitle"/>
                    </JobTitle>
                    <Job>
                        <xsl:value-of select="Item1"/>
                    </Job>
                    <CompOn>
                        <xsl:value-of select="substring-before(Item2,' ')"/>
                    </CompOn>
                    <CompAt>
                        <xsl:value-of select="substring-after(Item2,' ')"/>
                    </CompAt>
                </CompletedJob>

            </xsl:for-each>
         </Jobs>
    </xsl:template>

</xsl:stylesheet>

现在使用Level 3b元素将DoneBy解析为JobTitle。

答案 1 :(得分:1)

您不必使用嵌套循环(或循环)。

使用输入XML的固定版本:

<Level1>
  <Level2>
    <Level3a>
      <Item1>Clothes Washed</Item1>
      <Item2>08/02/2011 06:54</Item2>
      <DoneBy>Ingrid</DoneBy>
    </Level3a>
    <Level3a>
      <Item1>Car Washed</Item1>
      <Item2>08/02/2011 08:25</Item2>
      <DoneBy>Jeanette</DoneBy>
    </Level3a>
    <Level3a>
      <Item1>Dog Walked</Item1>
      <Item2>08/02/2011 10:30</Item2>
      <DoneBy>Ingrid</DoneBy>
    </Level3a>
    <Level3b>
      <DoneWho>Ingrid</DoneWho>
      <JobTitle>Main Asst</JobTitle>
    </Level3b>
    <Level3b>
      <DoneWho>Jeanette</DoneWho>
      <JobTitle>2nd Asst</JobTitle>
    </Level3b>
  </Level2>
</Level1>

和这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="/Level1">
    <Jobs>
      <xsl:apply-templates select="*/Level3a">
        <xsl:sort select="DoneBy"/>
      </xsl:apply-templates>
    </Jobs>
  </xsl:template>

  <xsl:template match="Level3a">
    <CompletedJob>
      <Who><xsl:apply-templates select="DoneBy"/></Who>
      <Job><xsl:apply-templates select="Item1"/></Job>
      <!-- XSLT 2.0 option
      <CompOn><xsl:value-of select="tokenize(Item2,' ')[1]"></xsl:value-of></CompOn>
      <CompAt><xsl:value-of select="tokenize(Item2,' ')[2]"></xsl:value-of></CompAt>
      -->
      <CompOn><xsl:value-of select="substring-before(Item2, ' ')"></xsl:value-of></CompOn>
      <CompAt><xsl:value-of select="substring-after(Item2, ' ')"></xsl:value-of></CompAt>
    </CompletedJob>
  </xsl:template>

  <xsl:template match="DoneBy|Item1|Item2">
    <xsl:apply-templates/>
  </xsl:template>

</xsl:stylesheet>

产生想要的输出:

<Jobs>
   <CompletedJob>
      <Who>Ingrid</Who>
      <Job>Clothes Washed</Job>
      <CompOn>08/02/2011</CompOn>
      <CompAt>06:54</CompAt>
   </CompletedJob>
   <CompletedJob>
      <Who>Ingrid</Who>
      <Job>Dog Walked</Job>
      <CompOn>08/02/2011</CompOn>
      <CompAt>10:30</CompAt>
   </CompletedJob>
   <CompletedJob>
      <Who>Jeanette</Who>
      <Job>Car Washed</Job>
      <CompOn>08/02/2011</CompOn>
      <CompAt>08:25</CompAt>
   </CompletedJob>
</Jobs>

注意:到目前为止,我的答案是唯一一个对输出进行排序并产生您想要的精确结果(减去格式错误)的答案。

答案 2 :(得分:0)

Darn,打败我吧。哦,不妨也提出我的解决方案:

<Level1>
    <Level2>
        <Level3>
            <Item1>Clothes Washed</Item1>
            <Item2>08/02/2011 06:54</Item2>
            <DoneBy>Ingrid</DoneBy>
        </Level3>
        <Level3>
            <Item1>Car Washed</Item1>
            <Item2>08/02/2011 08:25</Item2>
            <DoneBy>Jeanette</DoneBy>
        </Level3>
        <Level3>
            <Item1>Dog Walked</Item1>
            <Item2>08/02/2011 10:30</Item2>
            <DoneBy>Ingrid</DoneBy>
        </Level3>
    </Level2>
</Level1>


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <Jobs>
        <xsl:for-each select="/Level1/Level2/Level3">
            <CompletedJob>
                <Who><xsl:value-of select="./DoneBy"/></Who>
                <Job><xsl:value-of select="./Item1"/></Job>
                <CompOn><xsl:value-of select="substring(./Item2, 1, 10)"/></CompOn>
                <CompAt><xsl:value-of select="substring(./Item2, 12, 5)"/></CompAt>
            </CompletedJob>
        </xsl:for-each>
        </Jobs>
    </xsl:template>
</xsl:stylesheet>

答案 3 :(得分:0)

你的xml输入非常可怕。

    <xsl:template match="/">
    <xsl:apply-templates select="//Item1"/>
</xsl:template>

<xsl:template match="Item1">
    <CompletedJob>
        <Who><xsl:value-of select="../DoneBy"/></Who>
        <Job><xsl:value-of select="."/></Job>
        <xsl:apply-templates select="../Item2"/>
    </CompletedJob>
</xsl:template>

<xsl:template match="Item2">
    <CompOn><xsl:value-of select="substring-before(text(), ' ')"/></CompOn>
    <CompAt><xsl:value-of select="substring-after(text(), ' ')"/></CompAt>
</xsl:template>

这会生成输出