以下是示例xml文档。
<root>
<node> count the number of words </node>
</root>
对于这个例子,我想计算xslt中节点“”中的单词数。
输出就像是单词数量:: 5
对此有何想法?
您的(Dimitre Novatchev)代码适用于上述xml。 您的代码是否适用于以下xml?
<root>
<test>
<node> pass pass </node>
</test>
<test>
<node> fail pass fail </node>
</test>
<test>
<node> pass pass fail </node>
</test>
</root>
输出如:节点“node”中的单词总数:8
UPDATE3 ::
此代码完全适用于上述xml doc。 假设
<root>
<test>
<node> pass pass </node>
<a> value </a>
<b> value </b>
</test>
<test>
<node> fail fail </node>
<b> value </b>
</test>
<test>
<node> pass pass</node>
<a> value </a>
</test>
</root>
但是您的代码会计算整个文档中的单词数。 我想只计算节点类型“node”中的单词数。 输出如
“node”中的单词数:6 总传球:: 4 总失败:: 2
感谢名单 Sathish所在
答案 0 :(得分:11)
使用此XPath单行:
string-length(normalize-space(node))
-
string-length(translate(normalize-space(node),' ','')) +1
以下是使用XSLT的简短验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:value-of select=
" string-length(normalize-space(node))
-
string-length(translate(normalize-space(node),' ','')) +1"/>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<root>
<node> count the number of words </node>
</root>
产生了想要的正确结果:
5
解释:使用标准XPath函数normalize-space()
,translate()
和string-length()
。
<强> UPDATE1 强>:
OP问道:“你的(Dimitre Novatchev)代码是 上面的xml工作正常。是 您的代码将适用于以下内容 XML?“
<root> <test> <node> pass pass </node> </test> <test> <node> fail pass fail </node> </test> <test> <node> pass pass fail </node> </test> </root>
回答:可以使用相同的方法:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:value-of select=
"string-length(normalize-space(.))
-
string-length(translate(normalize-space(.),' ','')) +1
"/>
</xsl:template>
</xsl:stylesheet>
在新提供的XML文档(上面)上使用此转换时,会生成所需的正确答案:
8
Update2 :OP随后在评论中提问:
“我可以与...进行比较吗? 具有默认值的节点中的单词 字。 Conside节点包含值
"pass pass fail"
。我想算一算 通过次数和失败次数。 喜欢pass=2 fail=1
。可能吗? 帮帮我“
<强>答案强>:
同样的方法也适用于这个问题的修改(在一般情况下,你需要一个很好的标记化 - 请在新问题中询问我这个问题):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node">
pass: <xsl:value-of select=
"string-length()
-
string-length(translate(.,'p',''))
"/>
<xsl:text/> fail: <xsl:value-of select=
"string-length()
-
string-length(translate(.,'f',''))
"/>
</xsl:template>
</xsl:stylesheet>
当对最后一个XML文档(上面)应用此转换时,会生成所需的正确
pass: 2 fail: 0
pass: 1 fail: 2
pass: 2 fail: 1
答案 1 :(得分:1)
在xslt中我认为您需要处理以删除任何双倍间距,然后计算剩余空格以找到答案。虽然我确定有更好的方法!
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:for-each select="node">
<xsl:call-template name="word-count">
<xsl:with-param name="data" select="normalize-space(.)"/>
<xsl:with-param name="num" select="1"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="word-count">
<xsl:param name="data"/>
<xsl:param name="num"/>
<xsl:variable name="newdata" select="$data"/>
<xsl:variable name="remaining" select="substring-after($newdata,' ')"/>
<xsl:choose>
<xsl:when test="$remaining">
<xsl:call-template name="word-count">
<xsl:with-param name="data" select="$remaining"/>
<xsl:with-param name="num" select="$num+1"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$num = 1">
no words...
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$num"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这个示例代码有效,从我用过的样式表中修改了它,它将一些遗留代码处理成有用的html输出!
更新代码以改进错误,捕获重复的空格并捕获空节点:&gt;
更新以解决其他问题!
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="root">
<xsl:for-each select="test/node">
<xsl:call-template name="word-count">
<xsl:with-param name="data" select="normalize-space(.)"/>
<xsl:with-param name="num" select="1"/>
<xsl:with-param name="pass" select="0"/>
<xsl:with-param name="fail" select="0"/>
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="word-count">
<xsl:param name="data"/>
<xsl:param name="num"/>
<xsl:param name="fail"/>
<xsl:param name="pass"/>
<xsl:variable name="newdata" select="$data"/>
<xsl:variable name="first">
<xsl:choose>
<xsl:when test="substring-before($newdata,' ')">
<xsl:value-of select="substring-before($newdata,' ')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$newdata"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="remaining" select="substring-after($newdata,' ')"/>
<xsl:variable name="newpass">
<xsl:choose>
<xsl:when test="$first='pass'">
<xsl:value-of select="$pass+1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pass"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="newfail">
<xsl:choose>
<xsl:when test="$first='fail'">
<xsl:value-of select="$fail+1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$fail"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="$remaining">
<xsl:call-template name="word-count">
<xsl:with-param name="data" select="$remaining"/>
<xsl:with-param name="num" select="$num+1"/>
<xsl:with-param name="pass" select="$newpass"/>
<xsl:with-param name="fail" select="$newfail"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="$num = 1">
it was empty
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$first"/>
wordcount:<xsl:value-of select="$num"/>
pass:<xsl:value-of select="$newpass"/>
fail:<xsl:value-of select="$newfail"/><br/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:0)
这是我刚刚根据上面的Dimitre Novatchev的答案建立的XSLT。 它根据root / data / value计算单词(这适用于.NET资源文件[.RESX]),但您可以轻松地对其进行调整。
关于它使用的节点集函数,请参阅XSLT中提到的关于如何使用支持EXSLT的处理器或其他本机支持此函数的URL(使用msxml命名空间用于.NET / MSXML,可以很容易改变,以引用EXSLT等。)
<?xml version="1.0" encoding="UTF-8"?>
<!--
Filename: ResX_WordCount.xsl
Version: 20141006
-->
<xsl:stylesheet
version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="text" indent="yes"/>
<xsl:template match="/root">
<!-- see http://www.xml.com/pub/a/2003/07/16/nodeset.html -->
<xsl:variable name="WordCounts">
<xsl:for-each select="data/value">
<!-- see http://stackoverflow.com/questions/6188189/count-the-number-of-words-in-a-xml-node-using-xsl/ -->
<count>
<xsl:value-of select="string-length(normalize-space(text())) - string-length(translate(normalize-space(text()),' ','')) + 1"/>
</count>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="sum(msxsl:node-set($WordCounts)/count)"/>
</xsl:template>
</xsl:stylesheet>