我有一个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
,但我什么也没得到
有人可以看到我出错的地方吗?
命名空间及其前缀是正确的 - 在其他地方使用了且罚款。我觉得我围绕选择特定父节点的逻辑是错误的...
我需要坚持XSLT 1.0作为BizTalk驱动。
这几乎可以肯定是名称空间的问题。
在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与XML中的内容不匹配,则如果使用前缀,它将找不到元素。
因此,如果您使用此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()
,因为无论如何,内置模板将输出元素的文本。