我有以下XML:
<Root>
<PersonSettings>
<Type Drinks="1">A</Type>
<Type Drinks="2">B</Type>
<Type Drinks="3">C</Type>
<LowestAge>20</LowestAge>
<MaxAge>49</MaxAge>
</PersonSettings>
<PersonSettings>
<Type Drinks="5">A</Type>
<Type Drinks="8">B</Type>
<Type Drinks="1">C</Type>
<LowestAge>50</LowestAge>
<MaxAge>90</MaxAge>
</PersonSettings>
<Person Alive="Yes">
<Type>A</Type>
<Age>23</Age>
</Person>
<Person Alive="Yes">
<Type>B</Type>
<Age>50</Age>
</Person>
<Person Alive="Yes">
<Type>C</Type>
<Age>51</Age>
</Person>
<Person Alive="Yes">
<Type>A</Type>
<Age>70</Age>
</Person>
</Root>
以下XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="/">
<PersonsOneDrink>
<xsl:value-of select="(count(/Root/Person[@Alive = 'Yes' and /Root/PersonSettings[**(Person/Age)** >= LowestAge and **(Person/Age)** <= MaxAge]/Type[. = **(Person/Type)** and @Drinks = '1']))"/>
</PersonsOneDrink>
</xsl:template>
</xsl:stylesheet>
我想在这个例子中做的是计算一杯饮酒的人数,这些人还活着。根据人的类型和此人的年龄,我有不同的设置。例如,如果年龄在20到49岁之间,A型饮料有一种饮料,而如果在50到90岁之间,C型饮料有一种饮料。我发现的问题是当进入第二组括号时我无法引用外部节点。有没有办法动态创建变量?
P.S:带* *()* *的部分是我想引用外部节点的地方。
答案 0 :(得分:0)
我不认为可以使用从根的上下文应用的单个count()
表达式来完成此操作。
此处的问题是,您需要在谓词中引用Person
的值,并将它们与预期PersonSettings
的值进行比较。为此,您需要使用current()
function - 但为了让current()
函数引用Person
,您必须首先使Person
成为上下文节点。
这是一种建议的方法,为每个Person
写一个字符,将测试传递给变量。这样就无需在计算变量之前将变量转换为节点集:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Root">
<xsl:variable name="v1">
<xsl:for-each select="Person">
<xsl:if test="@Alive = 'Yes' and /Root/PersonSettings[LowestAge <= current()/Age and MaxAge >= current()/Age]/Type[. = current()/Type]/@Drinks = 1">
<xsl:text>Y</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<PersonsOneDrink>
<xsl:value-of select="string-length($v1)"/>
</PersonsOneDrink>
</xsl:template>
</xsl:stylesheet>
<强>结果强>
<?xml version="1.0" encoding="UTF-8"?>
<PersonsOneDrink>2</PersonsOneDrink>
更通用的解决方案 - 如果您想对提供的数据执行多个查询,则适合 - 首先重写输入并为每个Person
分配相应数量的饮料。
这里我们将构造一个包含以下内容的变量:
<Person>
<Type>A</Type>
<Age>23</Age>
<Drinks>1</Drinks>
</Person>
<Person>
<Type>B</Type>
<Age>50</Age>
<Drinks>8</Drinks>
</Person>
<Person>
<Type>C</Type>
<Age>51</Age>
<Drinks>1</Drinks>
</Person>
<Person>
<Type>A</Type>
<Age>70</Age>
<Drinks>5</Drinks>
</Person>
然后,一旦将变量转换为节点集,获得任意数量饮料的人数是微不足道的:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Root">
<!-- first pass -->
<xsl:variable name="persons-rtf">
<xsl:for-each select="Person">
<xsl:copy>
<xsl:copy-of select="*"/>
<Drinks>
<xsl:value-of select="/Root/PersonSettings[LowestAge <= current()/Age and MaxAge >= current()/Age]/Type[. = current()/Type]/@Drinks"/>
</Drinks>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="persons" select="exsl:node-set($persons-rtf)/Person"/>
<!-- output -->
<results>
<PersonsOneDrink>
<xsl:value-of select="count($persons[Drinks = 1])"/>
</PersonsOneDrink>
</results>
</xsl:template>
</xsl:stylesheet>