我有一个这样的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驱动。
答案 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()
,因为内置模板无论如何都会输出元素的文本。