XSLT для преобразования в XML некоторых тегов с количеством каждого тега - PullRequest
0 голосов
/ 31 января 2020

Как я могу преобразовать XML, который имеет что-то вроде этого:

<info>
   .....
   <name>aaa</name>
</info>
<info>
   .....
   <name>bbb</name>
</info>
<info>
   .....
   <name>ccc</name>
</info>

с XSLT, во что-то вроде этого:

<info>
   .....
   <name1>aaa</name1>
</info>
<info>
   .....
   <name2>bbb</name2>
</info>
<info>
   .....
   <name3>ccc</name3>
</info>

У кого-нибудь есть идеи? Спасибо!

Ответы [ 2 ]

1 голос
/ 31 января 2020

Я бы предложил использовать xsl:number вместо числа братьев и сестер:

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

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="info/name">
      <xsl:variable name="pos">
          <xsl:number count="info"/>
      </xsl:variable>
      <xsl:element name="{name()}{$pos}">
          <xsl:apply-templates/>
      </xsl:element>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/ejivJs7

Или в XSLT 3 использовать аккумулятор (работает даже с потоковой передачей):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy" use-accumulators="info-count" streamable="yes"/>

  <xsl:accumulator name="info-count" as="xs:integer" initial-value="0" streamable="yes">
      <xsl:accumulator-rule match="info" select="$value + 1"/>
  </xsl:accumulator>

  <xsl:template match="info/name">
      <xsl:element name="{name()}{accumulator-before('info-count')}">
          <xsl:apply-templates/>
      </xsl:element>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/ejivJs7/1

1 голос
/ 31 января 2020

В одном из подходов используется count(...) в сочетании с осью preceding-sibling:::

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

    <!-- Identity template -->    
    <xsl:template match="node()|@*">
      <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
      </xsl:copy>
    </xsl:template>

    <!-- Modify all 'name' elements -->
    <xsl:template match="name">
      <xsl:element name="{concat(name(),count(../preceding-sibling::info)+1)}">
        <xsl:apply-templates select="node()|@*" />
      </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Выход по желанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...