XSLT嵌套循环多个子元素

时间:2016-11-29 19:52:05

标签: xml xslt

我遇到了一个循环问题,需要小组的一些指示。我能够循环一个孩子,但在添加第二个孩子时遇到了麻烦。

这是我的XML:

<wd:Report_Entry>
  <wd:Beneficiaries_-_All>
    <wd:EMPLID>00025</wd:EMPLID>
    <wd:Last>LastName</wd:Last>
    <wd:First>FirstName</wd:First>
    <wd:WID>key1234</wd:WID>
  </wd:Beneficiaries_-_All>
  <wd:Beneficiaries_-_All>
    <wd:EMPLID>00025</wd:EMPLID>
    <wd:Last>LastName</wd:Last>
    <wd:First>First2</wd:First>
    <wd:WID>key4567</wd:WID>
  </wd:Beneficiaries_-_All>
  <wd:Beneficiaries_-_People>
    <wd:DOB>Birth1</wd:DOB>
    <wd:ID>ID1</wd:ID>
    <wd:WID>key1234</wd:WID>
  </wd:Beneficiaries_-_People>
  <wd:Beneficiaries_-_People>
    <wd:DOB>Birth2</wd:DOB>
    <wd:ID>ID2</wd:ID>
    <wd:WID>key4567</wd:WID>
  </wd:Beneficiaries_-_People>
</wd:Report_Entry>

我的XSLT在

之下
<xsl:output method="text"/>
<xsl:variable name="linefeed" select="'&#xA;'"></xsl:variable>

<xsl:template match="/">
 <xsl:for-each select="/wd:Report_Data/wd:Report_Entry">
   <xsl:for-each select="wd:Beneficiaries_-_All">
    <xsl:text>"</xsl:text>
    <xsl:value-of select="wd:EMPLID"/>
    <xsl:text>","</xsl:text>
    <xsl:value-of select="wd:Last"/>
    <xsl:text>","</xsl:text>
    <xsl:value-of select="wd:First"/>
    <xsl:text>","</xsl:text>
    <xsl:value-of select="$linefeed"/>
  </xsl:for-each>
  <xsl:for-each select="wd:Beneficiaries_-_People">
    <xsl:value-of select="wd:DOB"/>
    <xsl:text>","</xsl:text>
    <xsl:value-of select="wd:ID"/>
    <xsl:text>"</xsl:text>
  </xsl:for-each>
  <xsl:value-of select="$linefeed"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

我想要的输出是这样的CSV:

  

“00025”, “名字”, “First1”, “Birth1”, “ID1”
  “00025”, “姓氏”, “First2”, “Birth2”, “ID2”
  “00026”,“LastName”,“First1”,“Birth1”,“ID1”(以这种方式继续)

但我得到的每个报告条目:

  

“00025”, “名字”, “First1”,“
  “00025”, “姓氏”, “First2”,“
    Birth1“,”ID1“Birth2”,“ID2”

我对此网站的研究表明<apply-templates><for-each>更受欢迎。当我尝试这种方法时,格式给我一个问题。谢谢小组!

2 个答案:

答案 0 :(得分:1)

这是一个显示一些XSLT功能的解决方案:

  • 模板匹配(与wd相对)
  • XSL密钥
  • 多种模板模式

(我使用了<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wd="http://some.namespace/wd" > <xsl:output method="text" /> <xsl:key name="kPeople" match="wd:Beneficiaries_-_People" use="wd:WID" /> <xsl:template match="/"> <xsl:apply-templates select="wd:Report_Data/wd:Report_Entry/wd:Beneficiaries_-_All" /> </xsl:template> <xsl:template match="wd:Beneficiaries_-_All"> <xsl:apply-templates select="wd:EMPLID" mode="csv" /> <xsl:apply-templates select="wd:Last" mode="csv" /> <xsl:apply-templates select="wd:First" mode="csv" /> <xsl:apply-templates select="key('kPeople', wd:WID)/wd:DOB" mode="csv" /> <xsl:apply-templates select="key('kPeople', wd:WID)/wd:ID" mode="csv-nl" /> </xsl:template> <xsl:template match="*" mode="csv"> <xsl:value-of select="concat('&quot;', ., '&quot;,')" /> </xsl:template> <xsl:template match="*" mode="csv-nl"> <xsl:value-of select="concat('&quot;', ., '&quot;&#xA;')" /> </xsl:template> </xsl:stylesheet> 前缀的伪名称空间URI

"00025","LastName","FirstName","Birth1","ID1"
"00025","LastName","First2","Birth2","ID2"

对于您的样本数据,结果如下:

<wd:DOB>

陷阱:

  • 确保正确处理值中的双引号,否则CSV将被破坏。要么确保你删除它们或正确逃脱它们。做到这一点可能很棘手。
  • 如果某些XML元素(例如<xsl:apply-templates select="wd:EMPLID" mode="csv" /> )不存在,则不起作用。对于统一输入,元素总是在那里,但有时是空的,一切都很好。如果元素可能丢失,则需要更改脚本。

在这两种情况下:了解您的数据。

模板匹配是一把双刃剑。它非常适合输入驱动的转换。输入XML通过样式表中的模板进行映射,只需要很少的管道。

另一方面,CSV是一种严格的输出格式,以输入驱动的方式创建它需要输入同样严格。由于XML允许缺少元素,因此甚至可能没有可以转换为输出字段的元素。在这种情况下,命名模板和参数可以提供帮助:

而不是

<xsl:call-template name="csv">
  <xsl:with-param name="val" value="wd:EMPLID" />
</xsl:call-template>

我们可以

<xsl:template name="csv">
  <xsl:param name="val" />
  <xsl:value-of select="concat('&quot;', $val, '&quot;,')" />
</xsl:call-template>

"",

这样可以确保即使缺少元素,仍会打印空字段set(list1)

答案 1 :(得分:0)

如果我理解正确,你只需要一个变量就可以了:

<xsl:for-each select="/wd:Report_Data/wd:Report_Entry">
    <xsl:for-each select="wd:Beneficiaries_-_All">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="wd:EMPLID"/>
        <xsl:text>","</xsl:text>
        <xsl:value-of select="wd:Last"/>
        <xsl:text>","</xsl:text>
        <xsl:value-of select="wd:First"/>
        <xsl:text>","</xsl:text>
        <!-- new code starts here -->
        <xsl:variable name="WID" select="wd:WID"/>
        <xsl:value-of select="../wd:Beneficiaries_-_People[wd:WID = $WID]/wd:DOB"/>
        <xsl:text>","</xsl:text>
        <xsl:value-of select="../wd:Beneficiaries_-_People[wd:WID = $WID]/wd:ID"/>
        <xsl:text>"</xsl:text>
        <!-- end new code -->
        <xsl:value-of select="$linefeed"/>
    </xsl:for-each>
</xsl:for-each>

希望这有帮助!