2013-02-22 88 views
2

这似乎很简单,但我似乎无法让它工作。XSLT迭代子节点

我的XML看起来是这样的:

<bsar:BSAForm> 
    <bsar:SubjectInformation> 
     <bsar:LastNameOrNameOfEntity> Obama</bsar:LastNameOrNameOfEntity> 
     <bsar:AddressBlock> 
      <ucc:Address> 9 Dale Rd</ucc:Address> 
      <ucc:City> Woodbury</ucc:City> 
     </bsar:AddressBlock> 
     <bsar:AddressBlock> 
      <ucc:Address> 123 Fake St</ucc:Address> 
      <ucc:City> Springfield</ucc:City> 
     </bsar:AddressBlock> 
    </bsar:SubjectInformation> 
</bsar:BSAForm> 

我需要遍历这两个元素和显示内容。我的XSLT是这样的:

<xsl:template match=/bsar:BSAForm"> 
    <xsl:apply-templates select="bsar:SubjectInformation"/> 
</xsl:template> 

<xsl:template match="bsar:SubjectInformation"> 
    <xsl:text xml:space="preserve">4A</xsl:text> 
    <xsl:text xml:space="preserve">00001</xsl:text> 
    <xsl:value-of select="bsar:LastNameOrNameOfEntity"/> 
    <xsl:value-of select="'&#xD;&#xA;'"/> <!-- new line --> 

    <xsl:apply-templates select="bsar:AddressBlock"/> 
</xsl:template> 

<xsl:template match="bsar:AddressBlock"> 

    <xsl:variable name="Addr" select="../bsar:AddressBlock"/> 

    <xsl:text xml:space="preserve">4B</xsl:text> 
    <xsl:text xml:space="preserve">00001</xsl:text> 
    <xsl:value-of select="$Addr/ucc:Address"/> 
    <xsl:value-of select="$Addr/ucc:City"/> 
    <xsl:value-of select="'&#xD;&#xA;'"/> <!-- new line --> 
</xsl:template> 

输出应该如下:

4A 00001 Obama 
4B 9 Dale Rd Woodbury 
4B 123 Fake St Springfield 

而是输出出来是这样的:

4A 00001 Obama 
4B 9 Dale Rd Woodbury 
4B 9 Dale Rd Woodbury 

我已经尝试了许多不同的方法来做到这一点,每个使用一个,使用每个像这样:

<xsl:variable name="header" select="."/> 
<xsl:for-each select="following-sibling::bsar:TelephoneBlock[ancestor::bsar:SubjectInformation[1] = $header]"> 

或者甚至传递一个计数器从一个for循环和使用,以访问指定的元件是这样的:

<xsl:for-each select="bsar:TelephoneBlock"> 
    <xsl:variable name="Index"> 
     <xsl:number count="bsar:TelephoneBlock" /> 
    </xsl:variable> 

    <xsl:call-template name="SubjectPhone"> 
     <xsl:with-param name="$Index"/> 
    </xsl:call-template> 
</xsl:for-each> 

<xsl:template name="SubjectPhone"> 
    <xsl:param name="Index"/> 

    <xsl:variable name="Telephone" select="../bsar:TelephoneBlock[$Index]"/> 
    ... 
</xsl:template> 

在所有这些情况下,它是两次显示所述第一地址。请让我知道你是否注意到我做错了什么。

在此先感谢。

回答

3
<xsl:variable name="Addr" select="../bsar:AddressBlock"/> 

bsar:AddressBlock模板内将Addr变量设置为包含所有当前元素的父下bsar:AddressBlock元件节点集,即当前AddressBlock及其所有兄弟AddressBlock元素。当您以后来到

<xsl:value-of select="$Addr/ucc:Address"/> 

这将选择包含所有$Addr所有AddressBlock元素的ucc:Address子元素的节点集,然后在文档顺序第一这样的元素转换为它的字符串值(定义在XPath 1.0中设置的节点的“字符串值”是其第一个节点的字符串值)。这将始终是第一个AddressBlock中的ucc:Address,这就是您看到相同地址两次的原因。

但变量是联合国必要的,因为你适用于一个AddressBlock一次一个模板是 - 只是说

<xsl:template match="bsar:AddressBlock"> 
    <xsl:text>4B</xsl:text> 
    <xsl:text>00001</xsl:text> 
    <xsl:value-of select="ucc:Address"/> 
    <xsl:value-of select="ucc:City"/> 
    <xsl:value-of select="'&#xD;&#xA;'"/> <!-- new line --> 
</xsl:template> 

select表现将是相对于当前AddressBlock,并提取其地址和城市具体,并产生

4A00001 Obama 
4B00001 9 Dale Rd Woodbury 
4B00001 123 Fake St Springfield 

这并不依赖于一个事实,即有在原始XML每个地址和城市价值的开始领先的空间,你可能更愿意这样说

<xsl:template match="bsar:AddressBlock"> 
    <xsl:text>4B </xsl:text> 
    <xsl:text>00001 </xsl:text> 
    <xsl:value-of select="normalize-space(ucc:Address)"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="normalize-space(ucc:City)"/> 
    <xsl:value-of select="'&#xD;&#xA;'"/> <!-- new line --> 
</xsl:template> 

(注意xml:space="preserve"<xsl:text>默认的,所以你并不需要显式地指定它)

+0

你说得对。愿你活到一千岁。 – 2013-02-22 15:48:54