首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用XSLT计算XML中字符串出现的次数。

使用XSLT计算XML中字符串出现的次数。
EN

Stack Overflow用户
提问于 2011-07-13 13:30:22
回答 4查看 20.2K关注 0票数 7

我希望使用XSLT计算XML文档中特定节点中字符串出现的次数。考虑一下这个例子

代码语言:javascript
复制
 <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

怎么做?知道吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-07-13 13:33:14

使用

代码语言:javascript
复制
count(/*/*/list/language[contains(., 'java')])

完全XSLT转换

代码语言:javascript
复制
<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文档上应用时

代码语言:javascript
复制
<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>

想要的,正确的结果产生

代码语言:javascript
复制
 java -- 3

更新

如果我们要计算字符串的所有出现情况--不仅仅是包含字符串的所有节点--下面是如何做到这一点:

代码语言:javascript
复制
<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文档上应用此转换时的。

代码语言:javascript
复制
<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>

想要的,正确的结果产生

代码语言:javascript
复制
 java --- 4
票数 9
EN

Stack Overflow用户

发布于 2011-07-13 13:33:36

也许你可以试试这个用于计数子字符串的XSL模板

代码语言:javascript
复制
<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>

用法:

代码语言:javascript
复制
<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>
票数 2
EN

Stack Overflow用户

发布于 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‘可能在一个节点中存在不止一次,那么您将需要使用递归模板。有一种方法:

代码语言:javascript
复制
<?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会有很大帮助;如果每一种语言都有它自己的元素,这一切都是不必要的。当然,这可能超出了您的控制范围,但是如果您可以选择更改它(或者说服提供者更改它),我会强烈建议您这样做。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6679705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档