Xpath, как я могу получить общую длину строки всех атрибутов дочерних элементов родителя? - PullRequest
5 голосов
/ 28 февраля 2012

Довольно звездный вопрос, или я так подумал ...

select="../Store" возвращает набор узлов, содержащий все нужные мне узлы. Затем мне нужно вычислить длину строки атрибута name, прикрепленного к узлу Store.

Я бы подумал, что это будет так: select="string-length(../Store/@name)" но это только возвращает длину строки первого узла.

Есть идеи?

Ответы [ 4 ]

9 голосов
/ 28 февраля 2012

В 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

8 голосов
/ 08 марта 2012
<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)" />

Красиво и просто!

3 голосов
/ 28 февраля 2012

Я предполагаю, что ваш ввод 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 части.Это может быть отредактировано в соответствии.

3 голосов
/ 28 февраля 2012
sum(../Store/@name/string-length())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...