Xpath如何获取父级子级上所有属性的总字符串长度?

时间:2012-02-28 13:18:48

标签: xml xslt xpath

一个相当明星的前瞻性问题,或者我认为......

select="../Store"返回包含我需要的所有节点的节点集。然后,我需要计算附加到Store节点的name属性的字符串长度。

我原以为会是这样的: select="string-length(../Store/@name)"但这只返回第一个节点的字符串长度。

有什么想法吗?

4 个答案:

答案 0 :(得分:9)

在XPath 2.0中使用像这样的单个表达式

sum(../Store/@name/string-length(.))

使用单个XPath 1.0表达式无法做到这一点(不允许使用函数作为位置步骤),因此需要托管语言的一些帮助。

例如,如果托管语言是XSLT

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/*">
   <xsl:apply-templates select="Store[@name][1]"/>
 </xsl:template>

 <xsl:template match="Store[@name]">
  <xsl:param name="vAccum" select="0"/>

  <xsl:value-of select="$vAccum + string-length(@name)"/>
 </xsl:template>

 <xsl:template match="Store[@name and following-sibling::Store/@name]">
  <xsl:param name="vAccum" select="0"/>

  <xsl:apply-templates select="following-sibling::Store[@name][1]">
    <xsl:with-param name="vAccum" select="$vAccum + string-length(@name)"/>
  </xsl:apply-templates>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<root>
  <Store name="ab"/>
  <Store name="cde"/>
  <Store name="fgh"/>
  <Store name="ijklmn"/>
  <Store name="opr"/>
</root>

产生了想要的正确结果

17

答案 1 :(得分:8)

<xsl:variable name="StoreNames">
  <xsl:for-each select="../Store">
    <xsl:value-of select="@name"/>
  </xsl:for-each>
</xsl:variable>

<xsl:value-of select="string-length($StoreNames)" />

很好,很容易!

答案 2 :(得分:3)

sum(../Store/@name/string-length())

答案 3 :(得分:3)

我假设您的输入XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <Store name="data1"/>
  <Store name="data2"/>
  <Store name="data3"/>
  <Store name="data4"/>
  <Store name="data55"/>
</root>

这是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="text" indent="yes"/>
  <xsl:template match="/">
    <xsl:apply-templates select="node()"/>
  </xsl:template>

  <xsl:template match="Store[1]">
      <xsl:call-template name="calclength"/>
  </xsl:template>
  <xsl:template name="calclength">
    <xsl:param name="lengthsum" select="'0'"/>
    <xsl:variable name="newlengthsum" select="string-length(@name/.) + $lengthsum"/>
    <xsl:for-each select="following-sibling::Store[1]">
      <xsl:call-template name="calclength">
        <xsl:with-param name="lengthsum" select="$newlengthsum"/>
      </xsl:call-template>
    </xsl:for-each>
    <xsl:if test="not(following-sibling::Store[1])">
      LengthOfNameAttrs:
        <xsl:value-of select="$newlengthsum"/>

      Averagelength:
        <xsl:variable name="count" select="count(../Store)"/>
        <xsl:value-of select="$newlengthsum div $count"/>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>

输出是:

  LengthOfNameAttrs:
    26

  Averagelength:
    5.2

您只需为第一个calclength节点调用模板Store ..即,Store[1]它将计算并返回所有sibling-nodes的总和..只需使用这些XML和XSLT文件并执行它们。如果您在calling the template部分需要任何帮助,请与我们联系。它可以按照。

进行编辑