XSLT foreach 结合递归

XSLT foreach combined with recursion

我需要将 foreach 与我用 XSLT 编写的递归解决方案相结合。 问题写在下面。这个post从上往下看会更清楚

这是一个XML例子(原来的XML要大得多):

XML

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <GetAllResponse xmlns="z">
            <GetAllResult xmlns:i="y" xmlns:a="x">
                <a:OrganisatieEenheden>              
                    <a:OrganisatieEenheid>
                        <a:Code>1</a:Code>
                        <a:Omschrijving>Niveau1</a:Omschrijving>
                        <a:OrganisatieEenheidCrsNr>1001</a:OrganisatieEenheidCrsNr>
                        <a:ParentCode i:nil="true"/>
                    </a:OrganisatieEenheid>              
                    <a:OrganisatieEenheid>
                        <a:Code>2</a:Code>
                        <a:Omschrijving>Niveau2</a:Omschrijving>
                        <a:OrganisatieEenheidCrsNr>1002</a:OrganisatieEenheidCrsNr>
                        <a:ParentCode>1</a:ParentCode>
                    </a:OrganisatieEenheid>     
                    <a:OrganisatieEenheid>
                        <a:Code>8</a:Code>
                        <a:Omschrijving>Niveau8</a:Omschrijving>
                        <a:OrganisatieEenheidCrsNr>1008</a:OrganisatieEenheidCrsNr>
                        <a:ParentCode i:nil="true"/>
                    </a:OrganisatieEenheid>             
                    <a:OrganisatieEenheid>
                        <a:Code>3</a:Code>
                        <a:Omschrijving>Niveau3</a:Omschrijving>
                        <a:OrganisatieEenheidCrsNr>1003</a:OrganisatieEenheidCrsNr>
                        <a:ParentCode>2</a:ParentCode>
                    </a:OrganisatieEenheid>
                    <a:OrganisatieEenheid>
                        <a:Code>4</a:Code>
                        <a:Omschrijving>Niveau4</a:Omschrijving>
                        <a:OrganisatieEenheidCrsNr>1004</a:OrganisatieEenheidCrsNr>
                        <a:ParentCode>3</a:ParentCode>
                    </a:OrganisatieEenheid>
                </a:OrganisatieEenheden>
            </GetAllResult>
        </GetAllResponse>
    </soapenv:Body>
</soapenv:Envelope>

递归 XSLT (有关递归的其他信息可以在此 post 的底部找到)

<?xml version="1.0" encoding="UTF-8"?>
   <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:i="y"
                   xmlns:a="x"
                   version="1.0"
                   exclude-result-prefixes="a i">
      <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
      <xsl:param name="crs" select="1004"/>
      <xsl:key name="org-by-crs"
               match="a:OrganisatieEenheid"
               use="a:OrganisatieEenheidCrsNr"/>
      <xsl:key name="org-by-code" match="a:OrganisatieEenheid" use="a:Code"/>
      <xsl:template match="/">
         <OrganisatieEenheid>
            <Niveaus>
               <xsl:apply-templates select="key('org-by-crs', $crs)"/>
            </Niveaus>
            <OrganisatieEenheidCrsNr>
               <xsl:value-of select="$crs"/>
            </OrganisatieEenheidCrsNr>
         </OrganisatieEenheid>
      </xsl:template>
      <xsl:template match="a:OrganisatieEenheid">
         <xsl:if test="a:ParentCode[not(@i:nil='true')]">
            <xsl:apply-templates select="key('org-by-code', a:ParentCode)"/>
            <xsl:text>::</xsl:text>
         </xsl:if>
         <xsl:value-of select="a:Omschrijving"/>
      </xsl:template>
   </xsl:stylesheet>

输出递归 XSLT

<?xml version="1.0" encoding="utf-8"?>
<OrganisatieEenheid>
   <Niveaus>Niveau1::Niveau2::Niveau3::Niveau4</Niveaus>
   <OrganisatieEenheidCrsNr>1004</OrganisatieEenheidCrsNr>
</OrganisatieEenheid>

我也写了 foreach 函数,它接受所有 a:OrganisatieEenheidCrsNr

foreach XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   xmlns:i="y"
                   xmlns:a="x"
                   xmlns:ns2="z"
                   version="1.0"
                   exclude-result-prefixes="a i">
    <xsl:template match="/">
        <xsl:for-each select="//ns2:GetAllResponse/ns2:GetAllResult/a:OrganisatieEenheden/a:OrganisatieEenheid">
            <xsl:value-of select="a:OrganisatieEenheidCrsNr"/>  
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

每个 XSLT 的输出

<?xml version="1.0" encoding="UTF-8"?>10011002100810031004

问题

在递归函数中,我给出了 a:OrganisatieEenheidCrsNr,这将导致 1 个结果。 现在我需要一个解决方案来为 XML 中的每个 a:OrganisatieEenheidCrsNr 执行此操作。 所以我想我必须遍历所有数字并对每个数字执行递归。

上面XML例子中我需要的解决方案

<?xml version="1.0" encoding="utf-8"?>
<OrganisatieEenheden>
    <OrganisatieEenheid>
       <Niveaus>Niveau1</Niveaus>
       <OrganisatieEenheidCrsNr>1001</OrganisatieEenheidCrsNr>
    </OrganisatieEenheid>
    <OrganisatieEenheid>
       <Niveaus>Niveau1::Niveau2</Niveaus>
       <OrganisatieEenheidCrsNr>1002</OrganisatieEenheidCrsNr>
    </OrganisatieEenheid>
    <OrganisatieEenheid>
       <Niveaus>Niveau8</Niveaus>
       <OrganisatieEenheidCrsNr>1008</OrganisatieEenheidCrsNr>
    </OrganisatieEenheid>
    <OrganisatieEenheid>
       <Niveaus>Niveau1::Niveau2::Niveau3</Niveaus>
       <OrganisatieEenheidCrsNr>1003</OrganisatieEenheidCrsNr>
    </OrganisatieEenheid>
    <OrganisatieEenheid>
       <Niveaus>Niveau1::Niveau2::Niveau3::Niveau4</Niveaus>
       <OrganisatieEenheidCrsNr>1004</OrganisatieEenheidCrsNr>
    </OrganisatieEenheid>
</OrganisatieEenheden>

有关递归的其他信息

输入:OrganisatieEenheidCrsNr -> 1004 a:ParentCode 和 a:Code 是 Parent - Child 关系

当您输入 1004 时,它会搜索所有 parents 直到 a:ParentCode i:nil="true"。 然后从上到下打印所有由 :: 分隔的 Niveaus,并打印输入值。

得心应手的工具:http://xslttest.appspot.com/

谢谢你和我一起思考!

不,您不需要任何循环。

目前您将您的(完全正确的)结构应用于一个案例。您只需要将其应用于 所有 个案例。这意味着:摆脱变量,你就完成了。

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:i="y"
    xmlns:a="x"
    exclude-result-prefixes="a i"
>
  <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:key name="org-by-crs" match="a:OrganisatieEenheid" use="a:OrganisatieEenheidCrsNr"/>
  <xsl:key name="org-by-code" match="a:OrganisatieEenheid" use="a:Code"/>

  <xsl:template match="a:OrganisatieEenheden">
    <OrganisatieEenheden>
      <xsl:apply-templates select="a:OrganisatieEenheid" />
    </OrganisatieEenheden>
  </xsl:template>

  <xsl:template match="a:OrganisatieEenheid">
    <OrganisatieEenheid>
      <Niveaus>
        <xsl:apply-templates select="key('org-by-crs', a:OrganisatieEenheidCrsNr)" mode="niveaus" />
      </Niveaus>
      <OrganisatieEenheidCrsNr>
        <xsl:value-of select="a:OrganisatieEenheidCrsNr" />
      </OrganisatieEenheidCrsNr>
    </OrganisatieEenheid>
  </xsl:template>

  <xsl:template match="a:OrganisatieEenheid" mode="niveaus">
    <xsl:if test="a:ParentCode[not(@i:nil='true')]">
      <xsl:apply-templates select="key('org-by-code', a:ParentCode)" mode="niveaus" />
      <xsl:text>::</xsl:text>
    </xsl:if>
    <xsl:value-of select="a:Omschrijving" />
  </xsl:template>
</xsl:stylesheet>

结果:

<OrganisatieEenheden>
   <OrganisatieEenheid>
      <Niveaus>Niveau1</Niveaus>
      <OrganisatieEenheidCrsNr>1001</OrganisatieEenheidCrsNr>
   </OrganisatieEenheid>
   <OrganisatieEenheid>
      <Niveaus>Niveau1::Niveau2</Niveaus>
      <OrganisatieEenheidCrsNr>1002</OrganisatieEenheidCrsNr>
   </OrganisatieEenheid>
   <OrganisatieEenheid>
      <Niveaus>Niveau8</Niveaus>
      <OrganisatieEenheidCrsNr>1008</OrganisatieEenheidCrsNr>
   </OrganisatieEenheid>
   <OrganisatieEenheid>
      <Niveaus>Niveau1::Niveau2::Niveau3</Niveaus>
      <OrganisatieEenheidCrsNr>1003</OrganisatieEenheidCrsNr>
   </OrganisatieEenheid>
   <OrganisatieEenheid>
      <Niveaus>Niveau1::Niveau2::Niveau3::Niveau4</Niveaus>
      <OrganisatieEenheidCrsNr>1004</OrganisatieEenheidCrsNr>
   </OrganisatieEenheid>
</OrganisatieEenheden>