XSLT1选择兄弟姐妹的子节点值

时间:2012-11-08 12:17:13

标签: xslt xslt-1.0 biztalk biztalk-mapper

我有一个这样的XML文档:

(p先前已定义)

<p:Players>
<p:Player>
<p:Name>David</p:Name>
<p:Club>
<p:Name>Madrid</p:Name>
</p:Club>
<p:PreviousClubs>
<p:Club><p:Name>Milan</p:Name></p:Club>
<p:Club><p:Name>Manchester</p:Name></p:Club>
</p:PreviousClubs>
</p:Player>
<p:Player>
<p:Name>Alex</p:Name>
<p:Club>
<p:Name>Madrid</p:Name>
</p:Club>
<p:PreviousClubs>
<p:Club><p:Name>Birmingham</p:Name></p:Club>
<p:Club><p:Name>Manchester</p:Name></p:Club>
</p:PreviousClubs>
</p:Player>
<p:Player>
<p:Name>Fred</p:Name>
<p:Club>
<p:Name>Madrid</p:Name>
</p:Club>
<p:PreviousClubs>
<p:Club><p:Name>Milan</p:Name></p:Club>
<p:Club><p:Name>Birmingham</p:Name></p:Club>
</p:PreviousClubs>
</p:Player>
</p:Players>

我想获得之前为特定俱乐部效力的所有球员的名字。

这是我到目前为止所做的,但它没有采取任何措施:

/*[1]/p:Player[p:PreviousClubs/p:Club/p:Name='Manchester']/p:Name/text()

我希望返回

David
Alex

但我什么都没得到

有人能看到我出错的地方吗?

p:的名称空间及其前缀是正确的 - 已在其他地方使用并且很好。我觉得我选择特定父节点的逻辑是错误的......

我需要坚持使用XSLT 1.0作为其BizTalk驱动。

1 个答案:

答案 0 :(得分:1)

这几乎肯定是名称空间的问题。

在XML中,您使用的是命名空间前缀,但命名空间没有相应的定义。你应该在根元素

上有一个这样的定义
<p:Players xmlns:p="mynamespace">

然后,在XSLT中,您还需要确保定义了相同的名称空间URI。

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:p="mynamespace">

请注意,前缀 p 不必相同。这里的名称空间URI是重要的标识符。如果URI与XML中的URI不匹配,则在使用前缀时将无法找到元素。

如果您因此使用此XSLT,它应该按预期返回 David Alex (尽管如果您想要在此处换行,则需要添加额外的代码)

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:p="mynamespace">

    <xsl:template match="/">
       <xsl:apply-templates 
           select="/*[1]/p:Player[p:PreviousClubs/p:Club/p:Name='Manchester']/p:Name/text()" />
    </xsl:template>
</xsl:stylesheet>

这一切都意味着你原来的XPath表达是正确的!但是,您可以略微简化,因为一开始就不需要[1]。第一个/匹配文档元素,因此/*将匹配根元素,并且因为在格式良好的XML中只能有一个根元素,所以不需要使用索引限定它[1]

/*/p:Player[p:PreviousClubs/p:Club/p:Name='Manchester']/p:Name/text()

您也可以在最后删除text(),因为内置模板无论如何都会输出元素的文本。