XSL 嵌入式 for-each

发布于 2024-11-30 07:43:03 字数 2027 浏览 0 评论 0原文

我知道这里对此有所介绍,但我是 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>

:请查看上面输出中的更改...我想这确实是我想要做的。 将输出替换为 ... 再次感谢。

我尝试过嵌套 for-each 循环,但无法从主 for-each 循环内部引用不同的节点。

非常感谢任何帮助。

I know this is covered somewhat on here, but I'm new to XSLT and I'm trying to do a nested for-each loop on nodes that are in different places in the input XML but at the same node level.

So...for example:

    <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>

I need the output to be

    <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>

EDIT: please see the change in the above output...I guess this is really what I'm trying to do.
Replacing in output with ...thanks again.

I've tried a neste for-each loop, but I can't refer to a different node from inside the main for-each loop.

Any help is greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦年海沫深 2024-12-07 07:43:03

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

使用输入 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>

注意:到目前为止,我的答案是唯一对输出进行排序并生成准确结果(减去格式良好错误)的答案。通缉。

You shouldn't have to use nested loops (or loops at all).

Using a fixed version of the input 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>

and this stylesheet:

<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>

produces the wanted output:

<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>

NOTE: So far, my answer is the only one that sorts the output and produces the exact result (minus the well-formedness error) you wanted.

怪我闹别瞎闹 2024-12-07 07:43:03

不需要嵌套循环 - 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>

Level3b 元素现在用于将 DoneBy 解析为 JobTitle。

No need for nested loops - XSLT is resursive enough by nature.

Following stylesheet does the job:

<?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>

Level3b elements are now used for resolving DoneBy to JobTitle.

娇女薄笑 2024-12-07 07:43:03

该死,打败我了。哦,好吧,不妨也给出我的解决方案:

<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>

Darn, beat me to it. Oh well, might as well give my solution too:

<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>
空心空情空意 2024-12-07 07:43:03

你的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>

这会生成你的输出

your xml input is realy terrible.

    <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>

this generates your output

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文