这看起来很简单,但我似乎无法让它发挥作用。
我的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="'
'"/> <!-- 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="'
'"/> <!-- 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>
在所有这些情况下,它会两次显示第一个地址。如果你注意到我做错了什么,请告诉我。
提前谢谢。
<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="'
'"/> <!-- new line -->
</xsl:template>
select
表达式将与当前AddressBlock相关,并将具体提取其Address和City,并生成
4A00001 Obama
4B00001 9 Dale Rd Woodbury
4B00001 123 Fake St Springfield
这确实依赖于这样一个事实,即在原始XML中的每个Address和City值的开头都有一个前导空格,您可能更喜欢说类似的内容
<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="'
'"/> <!-- new line -->
</xsl:template>
(注意,xml:space="preserve"
是<xsl:text>
的默认值,因此不需要显式指定)