我正在尝试使用XSLT将1个XML文件转换为另一个XML文件,其中生成的XML文件是执行查询的结果。不幸的是,根据我的理解,XSLT中的变量是不可变的,无法更改。我想知道是否有任何其他方法可以添加值,以便我可以获得为相关部分返回的任何查询的总值。
正如您在原始XML文件中看到的那样,总数会计算每个条目中所有年龄组编号的总值。我使用XSLT查询根据查询的年龄范围$ AGE_GROUP1和$ AGE_GROUP2提取出不同的年龄组,但由于任何声明的变量都是不可变的,我想不出一种方法来添加年龄组的查询值
以下是源XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<Replacements>
<Entry>
<Year>2005</Year>
<Month>DEC</Month>
<Reason>Blemish on Card</Reason>
<Age>
<Group>
<Range>Total</Range>
<value>16</value>
</Group>
<Group>
<Range>16-17</Range>
<value>3</value>
</Group>
<Group>
<Range>18-25</Range>
<value>12</value>
</Group>
<Group>
<Range>26-29</Range>
<value>1</value>
</Group>
</Age>
</Entry>
<Entry>
<Year>2005</Year>
<Month>DEC</Month>
<Reason>Damaged</Reason>
<Age>
<Group>
<Range>Total</Range>
<value>7</value>
</Group>
<Group>
<Range>16-17</Range>
<value>6</value>
</Group>
<Group>
<Range>18-25</Range>
<value>0</value>
</Group>
<Group>
<Range>26-29</Range>
<value>1</value>
</Group>
</Age>
</Entry>
</Replacements>
以下XSLT仅提取3个年龄组中的相关2个(仅提取14至24岁的年龄组),因此原始数据集中每个条目的1个年龄组不会输出到生成的XML文件:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:variable name = "QUERY_YEAR1" select = "2005" />
<xsl:variable name = "QUERY_YEAR2" select = "2007" />
<xsl:variable name = "AGE_GROUP1" select = "14" />
<xsl:variable name = "AGE_GROUP2" select = "24" />
<xsl:variable name = "TOTAL" select = "0" />
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:for-each select="Replacements/Entry">
<xsl:if test="$QUERY_YEAR1 <= Year/text() and $QUERY_YEAR2 >= Year/text()">
<Entry>
<Year>
<xsl:value-of select="Year/text()" />
</Year>
<Month>
<xsl:value-of select="Month/text()" />
</Month>
<Reason>
<xsl:value-of select="Reason/text()" />
</Reason>
<xsl:for-each select="Age/Group">
<!-- $AGE_GROUP1 < 16 & 17, $AGE_GROUP2 > 16 & 17 for age group 16-17 (e.g. $AGE_GROUP1 = 14 & $AGE_GROUP2 = 30 -->
<xsl:if test="$AGE_GROUP1 <= number(substring(Range/text(), 1, 2)) and $AGE_GROUP1 <= number(substring(Range/text(), 4, 2)) and $AGE_GROUP2 >= number(substring(Range/text(), 1, 2)) and $AGE_GROUP2 >= number(substring(Range/text(), 4, 2)) and not(Range/text() = 'Total') and not(Range/text() = '80+')">
<!-- Add to $TOTAL value -->
<xsl:variable name = "TOTAL" select = "number($TOTAL) + number(value/text())" />
<AgeGroup>
<Range>
<xsl:value-of select="Range/text()" />
</Range>
<value>
<xsl:value-of select="value/text()" />
</value>
</AgeGroup>
</xsl:if>
<!-- $AGE_GROUP1 < 30 & 39, $AGE_GROUP2 = 30 & < 39 for age group 30-39 (e.g. $AGE_GROUP1 = 14 & $AGE_GROUP2 = 30 -->
<!-- $AGE_GROUP1 < 26 & 29, $AGE_GROUP2 > 26 & < 29 for age group 26-29 (e.g. $AGE_GROUP1 = 19 & $AGE_GROUP2 = 27 -->
<xsl:if test="$AGE_GROUP1 <= number(substring(Range/text(), 1, 2)) and $AGE_GROUP1 <= number(substring(Range/text(), 4, 2)) and $AGE_GROUP2 >= number(substring(Range/text(), 1, 2)) and $AGE_GROUP2 <= number(substring(Range/text(), 4, 2)) and not(Range/text() = 'Total') and not(Range/text() = '80+')">
<!-- Add to $TOTAL value -->
<xsl:variable name = "TOTAL" select = "number($TOTAL) + number(value/text())" />
<AgeGroup>
<Range>
<xsl:value-of select="Range/text()" />
</Range>
<value>
<xsl:value-of select="value/text()" />
</value>
</AgeGroup>
</xsl:if>
<!-- $AGE_GROUP1 > 18 & < 25, $AGE_GROUP2 > 18 & 25 for age group 18-25 (e.g. $AGE_GROUP1 = 19 & $AGE_GROUP2 = 27 -->
<xsl:if test="$AGE_GROUP1 >= number(substring(Range/text(), 1, 2)) and $AGE_GROUP1 <= number(substring(Range/text(), 4, 2)) and $AGE_GROUP2 >= number(substring(Range/text(), 1, 2)) and $AGE_GROUP2 >= number(substring(Range/text(), 4, 2)) and not(Range/text() = 'Total') and not(Range/text() = '80+')">
<!-- Add to $TOTAL value -->
<xsl:variable name = "TOTAL" select = "number($TOTAL) + number(value/text())" />
<AgeGroup>
<Range>
<xsl:value-of select="Range/text()" />
</Range>
<value>
<xsl:value-of select="value/text()" />
</value>
</AgeGroup>
</xsl:if>
</xsl:for-each>
<!-- Total calculation for all values within returned age groups -->
<AgeGroup>
<Range>
<xsl:value-of select="'Total'" />
</Range>
<value>
<xsl:value-of select="$TOTAL" />
</value>
</AgeGroup>
</Entry>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我现在得到的是以下内容,它没有提取的年龄组值的总值,因为我无法在每个时刻分配变量$ TOTAL:
<?xml version="1.0" encoding="UTF-8"?>
<Entry>
<Year>2005</Year>
<Month>DEC</Month>
<Reason>Blemish on Card</Reason>
<AgeGroup>
<Range>16-17</Range>
<value>3</value>
</AgeGroup>
<AgeGroup>
<Range>18-25</Range>
<value>12</value>
</AgeGroup>
<AgeGroup>
<Range>Total</Range>
<value>0</value>
</AgeGroup>
</Entry>
<Entry>
<Year>2005</Year>
<Month>DEC</Month>
<Reason>Damaged</Reason>
<AgeGroup>
<Range>16-17</Range>
<value>6</value>
</AgeGroup>
<AgeGroup>
<Range>18-25</Range>
<value>0</value>
</AgeGroup>
<AgeGroup>
<Range>Total</Range>
<value>0</value>
</AgeGroup>
</Entry>
我需要的是:
<?xml version="1.0" encoding="UTF-8"?>
<Entry>
<Year>2005</Year>
<Month>DEC</Month>
<Reason>Blemish on Card</Reason>
<AgeGroup>
<Range>16-17</Range>
<value>3</value>
</AgeGroup>
<AgeGroup>
<Range>18-25</Range>
<value>12</value>
</AgeGroup>
<AgeGroup>
<Range>Total</Range>
<value>15</value>
</AgeGroup>
</Entry>
<Entry>
<Year>2005</Year>
<Month>DEC</Month>
<Reason>Damaged</Reason>
<AgeGroup>
<Range>16-17</Range>
<value>6</value>
</AgeGroup>
<AgeGroup>
<Range>18-25</Range>
<value>0</value>
</AgeGroup>
<AgeGroup>
<Range>Total</Range>
<value>6</value>
</AgeGroup>
</Entry>
我用来执行XSLT的命令是:java -jar saxon9he.jar sample1.xml sample1.xslt > out.xml
我只是想知道是否有人知道如何添加值,就像输入if条件时在XSLT中看到的那样,以便将该年龄组的值添加到总数中,并且总计可以在输出XML文件中返回吗?
答案 0 :(得分:1)
我认为,不是有三个单独的表达式来测试重叠范围,你可以将它减少到只有一个条件....
<xsl:for-each select="Age/Group
[$AGE_GROUP1 <= number(substring(Range/text(), 4, 2))]
[$AGE_GROUP2 >= number(substring(Range/text(), 1, 2))]">
但是就获得总数而言,您只需使用sum
函数来总结所有value
元素。您可以将上面的表达式放在变量...
<xsl:variable name="groups" select="Age/Group[$AGE_GROUP1 <= number(substring(Range/text(), 4, 2))][$AGE_GROUP2 >= number(substring(Range/text(), 1, 2))]" />
然后你得到总数如下:
<xsl:value-of select="sum($groups/value)" />
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:variable name = "QUERY_YEAR1" select = "2005" />
<xsl:variable name = "QUERY_YEAR2" select = "2007" />
<xsl:variable name = "AGE_GROUP1" select = "14" />
<xsl:variable name = "AGE_GROUP2" select = "24" />
<xsl:variable name = "TOTAL" select = "0" />
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/">
<xsl:for-each select="Replacements/Entry">
<xsl:if test="$QUERY_YEAR1 <= Year/text() and $QUERY_YEAR2 >= Year/text()">
<Entry>
<Year>
<xsl:value-of select="Year/text()" />
</Year>
<Month>
<xsl:value-of select="Month/text()" />
</Month>
<Reason>
<xsl:value-of select="Reason/text()" />
</Reason>
<xsl:variable name="groups" select="Age/Group[$AGE_GROUP1 <= number(substring(Range/text(), 4, 2))][$AGE_GROUP2 >= number(substring(Range/text(), 1, 2))]" />
<xsl:for-each select="$groups">
<AgeGroup>
<Range>
<xsl:value-of select="Range/text()" />
</Range>
<value>
<xsl:value-of select="value/text()" />
</value>
</AgeGroup>
</xsl:for-each>
<!-- Total calculation for all values within returned age groups -->
<AgeGroup>
<Range>
<xsl:value-of select="'Total'" />
</Range>
<value>
<xsl:value-of select="sum($groups/value)" />
</value>
</AgeGroup>
</Entry>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
编辑:在回答您的评论时,如果您的年龄范围为&#34; 80 +&#34;我想你可以像这样调整groups
变量:
<xsl:variable name="groups" select="Age/Group
[substring(Range/text(), 3, 1) = '+' or $AGE_GROUP1 <= number(substring(Range/text(), 4, 2))]
[$AGE_GROUP2 >= number(substring(Range/text(), 1, 2))]" />