我的XML代码(包含酒吧和人):
<document>
<pubs>
<pub id="pub1">
<open>true</open>
</pub>
<pub id="pub2">
<open>false</open>
</pub>
</pubs>
<people>
<person>
<name>John</name>
<pubId>pub1</pubId>
</person>
<person>
<name>Paul</name>
<pubId>pub2</pubId>
</person>
</people>
</document>
使用<person>
到<pub>
(person/pubId
引用pub[@id]
)的引用。酒吧本身有一个布尔<open>
(说明酒吧是打开还是关闭)。
使用XSLT,我希望能够count()
可以去酒吧的人数。要前往酒吧,酒吧的<open>
值必须为true
。
我无法编写的两种可能的解决方案:
通过人员进行迭代并跟踪数字:
<xsl:for-each select="person">
<xsl:variable name="pId" select="pubId" />
<xsl:if test="root()/document/pubs/pub[@pubId=$pId]/open = 'true'" >
<!-- any way to keep track of this number? -->
</xsl:if>
</xsl:for-each>
直接使用count()函数:
<count>
<xsl:value-of select="count(//person[root()/document/pubs/pub[@id = pubId]/open = 'true'])" />
</count>
第二个选项似乎更简洁和正确,但我无法让它工作。
有什么想法吗?
答案 0 :(得分:1)
使用此XPath 1.0一行:
count(/*/people/person[pubId = /*/pubs/pub[open = 'true']/@id])
这将返回此文档中至少有一个person
子元素的pubId
元素的数量,以便有一个pub
元素,其id
属性的字符串值等于pubId
及其open
子项的字符串值为字符串"true"
。
以下是基于XSLT的验证:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:copy-of select=
"count(/*/people/person[pubId = /*/pubs/pub[open = 'true']/@id])"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<document>
<pubs>
<pub id="pub1">
<open>true</open>
</pub>
<pub id="pub2">
<open>false</open>
</pub>
</pubs>
<people>
<person>
<name>John</name>
<pubId>pub1</pubId>
</person>
<person>
<name>Paul</name>
<pubId>pub2</pubId>
</person>
</people>
</document>
评估Xpath表达式并将此评估结果复制到输出中:
1
答案 1 :(得分:0)
您可以尝试使用密钥查找酒吧
<xsl:key name="pubs" match="pub" use="@id" />
这样您就可以将计数简化为以下
<xsl:value-of select="count(//person[key('pubs', pubId)[open='true']])"/>
因此,对于以下XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="pubs" match="pub" use="@id" />
<xsl:template match="/">
<count>
<xsl:value-of select="count(//person[key('pubs', pubId)[open='true']])"/>
</count>
</xsl:template>
</xsl:stylesheet>
以下是输出
<count>1</count>
请注意,在XSLT中,变量是不可变的,一旦设置就无法更改。因此,您尝试设置变量和增量的第一种方法无效。
答案 2 :(得分:0)
是的,第二种方法是正确的:它基本上是在进行连接。正如Tim C指出的那样,密钥通常对在XSLT中进行连接很有用。
您尝试的原因
count(//person[root()/document/pubs/pub[@id = pubId]/open = 'true'])
不起作用是'pubId'的上下文是错误的。您可以使用范围变量在XPath 2.0中解决此问题:
count(for $p in //person return (if (/document/pubs/pub[@id = $p/pubId]/open = 'true') then $p else ()))
但使用键更简单,更快。