我希望使用XSLT计算XML文档中特定节点中字符串出现的次数。考虑一下这个例子
<mainNode>
<book>
<price> 100 </price>
<city> chennai </city>
<list>
<language> c java ruby </language>
</list>
</book>
<book>
<price> 200 </price>
<city> banglore </city>
<list>
<language> c java </language>
</list>
</book>
<book>
<price> 300 </price>
<city> delhi </city>
<list>
<language> java ruby </language>
</list>
</book>
</mainNode> 在这里,我想计算一下"java“的出现。
我希望输出如下::Java-3
怎么做?知道吗?
发布于 2011-07-13 13:33:14
使用
count(/*/*/list/language[contains(., 'java')])完全XSLT转换
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
java -- <xsl:value-of select=
"count(/*/*/list/language[contains(., 'java')]) "/>
</xsl:template>
</xsl:stylesheet>在提供的XML文档上应用时
<mainNode>
<book>
<price> 100 </price>
<city> chennai </city>
<list>
<language> c java ruby </language>
</list>
</book>
<book>
<price> 200 </price>
<city> banglore </city>
<list>
<language> c java </language>
</list>
</book>
<book>
<price> 300 </price>
<city> delhi </city>
<list>
<language> java ruby </language>
</list>
</book>
</mainNode>想要的,正确的结果产生
java -- 3更新
如果我们要计算字符串的所有出现情况--不仅仅是包含字符串的所有节点--下面是如何做到这一点:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:param name="pWord" select="' java '"/>
<xsl:template match="/">
<xsl:variable name="vResult">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="concat($pWord, '--- ')"/>
<xsl:value-of select="string-length($vResult)"/>
</xsl:template>
<xsl:template match="list/language" name="countWord">
<xsl:param name="pText" select="."/>
<xsl:if test="contains($pText, $pWord)">
<xsl:text>X</xsl:text>
<xsl:call-template name="countWord">
<xsl:with-param name="pText"
select="concat(' ', substring-after($pText, $pWord))"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>在此XML文档上应用此转换时的。
<mainNode>
<book>
<price> 100 </price>
<city> chennai </city>
<list>
<language> c java ruby </language>
</list>
</book>
<book>
<price> 200 </price>
<city> banglore </city>
<list>
<language> c java </language>
</list>
</book>
<book>
<price> 300 </price>
<city> delhi </city>
<list>
<language> java java ruby </language>
</list>
</book>
</mainNode>想要的,正确的结果产生
java --- 4发布于 2011-07-13 13:33:36
也许你可以试试这个用于计数子字符串的XSL模板
<xsl:template name="substring-count">
<xsl:param name="string"/>
<xsl:param name="substr"/>
<xsl:choose>
<xsl:when test="contains($string, $substr) and $string and $substr">
<xsl:variable name="rest">
<xsl:call-template name="substring-count">
<xsl:with-param name="string" select="substring-after($string, $substr)"/>
<xsl:with-param name="substr" select="$substr"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$rest + 1"/>
</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>用法:
<xsl:call-template name="substring-count">
<xsl:with-param name="string" select="'mary had a little lamb'" />
<xsl:with-param name="substr" select="'lamb'" />
</xsl:call-template>发布于 2011-07-13 13:41:43
在<xsl:value-of>语句中尝试这样做:
count(//language[contains(concat(' ',.,' '), ' java ')])
如果您的文档结构是相对静态的,或者在其他地方有名为language的节点用于其他目的,则可以用//language代替/mainNode/book/list/language。
concat位看起来有点复杂,但是通过确保在文本的开头和结尾都有一个空格,并且搜索' java '的两边都有一个空格,您不会错误地包含其他碰巧包含java的术语,比如javascript。
如果'java‘可能在一个节点中存在不止一次,那么您将需要使用递归模板。有一种方法:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:variable name="list">
<xsl:for-each select="//language">
<xsl:call-template name="count">
<xsl:with-param name="lang">java</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="concat('java -- ',string-length($list))" />
</xsl:template>
<xsl:template name="count">
<xsl:param name="lang" />
<xsl:param name="text" select="text()" />
<xsl:if test="contains(concat(' ',$text,' '),concat(' ',$lang,' '))">
<xsl:text>0</xsl:text>
<xsl:call-template name="count">
<xsl:with-param name="lang" select="$lang" />
<xsl:with-param name="text" select="substring-after($text,$lang)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>这实际上创建了一个0的字符串,每个java出现一个字符串,然后简单地使用该字符串的长度。
如果您可以选择使用XSLT2.0,则可以创建一个计算字符串中出现的次数的函数,并使用<xsl:value-of select="sum(mycountfunction(//language))" />或类似的方法。
正如我在对您的问题发表的评论中指出的那样,更好地设计源XML会有很大帮助;如果每一种语言都有它自己的元素,这一切都是不必要的。当然,这可能超出了您的控制范围,但是如果您可以选择更改它(或者说服提供者更改它),我会强烈建议您这样做。
https://stackoverflow.com/questions/6679705
复制相似问题