Как сделать добавление элемента во вложенный список с преобразованием? - PullRequest
1 голос
/ 18 мая 2011

Предположим, у нас есть такой вложенный список в XML:

<section name="SomeSection">
    <!-- list property -->
    <property length="2" name="ExternalList">
        <!-- first element of external list -->
        <listItem name="ExtElement1">
            <property length="3" name="InternalList1">
                <listItem name="SomeElement1" />
                <listItem name="SomeElement2" />
                <listItem name="SomeElement3" />
            </property>
        </listItem>
        <!-- second element of external list -->
        <listItem name="ExtElement2">
            <property length="2" name="InternalList1">
                <listItem name="SomeElement1" />
                <listItem name="SomeElement2" />
            </property>
        </listItem>
    </property>
</section>

И у нас есть новый элемент, например:

<listItem name="SomeElement3" />

Какое преобразование добавляет SomeElement3 к InternalList1 в«ExtElement2», а также увеличивает атрибут «length» для InternalList1?

Спасибо.

Ответы [ 2 ]

1 голос
/ 18 мая 2011

Это короткое и простое преобразование использует и переопределяет правило идентификации :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match=
 "property[@name='ExternalList']
     /listItem[@name='ExtElement2']
       /property[@name='InternalList1']
 ">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:attribute name="length">
    <xsl:value-of select="@length+1"/>
   </xsl:attribute>
   <xsl:apply-templates/>
   <listItem name="SomeElement3" />
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML:

<section name="SomeSection">
    <!-- list property -->
    <property length="2" name="ExternalList">
        <!-- first element of external list -->
        <listItem name="ExtElement1">
            <property length="3" name="InternalList1">
                <listItem name="SomeElement1" />
                <listItem name="SomeElement2" />
                <listItem name="SomeElement3" />
            </property></listItem>
        <!-- second element of external list -->
        <listItem name="ExtElement2">
            <property length="2" name="InternalList1">
                <listItem name="SomeElement1" />
                <listItem name="SomeElement2" />
            </property></listItem>
    </property>
</section>

желаемый, правильный результат получается :

<section name="SomeSection"><!-- list property -->
   <property length="2" name="ExternalList"><!-- first element of external list -->
      <listItem name="ExtElement1">
         <property length="3" name="InternalList1">
            <listItem name="SomeElement1"/>
            <listItem name="SomeElement2"/>
            <listItem name="SomeElement3"/>
         </property>
      </listItem><!-- second element of external list -->
      <listItem name="ExtElement2">
         <property length="3" name="InternalList1">
            <listItem name="SomeElement1"/>
            <listItem name="SomeElement2"/>
            <listItem name="SomeElement3"/>
         </property>
      </listItem>
   </property>
</section>

Примечание: Абсолютно никакие условные инструкции XSLT нигде в этом решении не используются - они вообще не нужны.

0 голосов
/ 18 мая 2011

Вот простая таблица стилей, которая принимает детали нового элемента в качестве параметров:

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

  <xsl:param name="extElement" select="'ExtElement2'" />
  <xsl:param name="intElement" select="'SomeElement3'" />

  <xsl:template match="property[@name='ExternalList']/listItem">
    <xsl:choose>
      <xsl:when test="@name = $extElement">
        <listItem name="{$extElement}">
          <property length="{property/@length+1}" name="{property/@name}">
            <xsl:apply-templates select="property/listItem" />
            <listItem name="{$intElement}" />
          </property>
        </listItem>
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="identity" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

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

Или, если вы хотите жестко закодировать его в таблицу стилей, вы можете сделать:

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

  <xsl:template match="listItem[@name='ExtElement2']/property">
    <property length="{@length + 1}">
      <xsl:apply-templates select="@*[name() != 'length'] | node()"/>
      <listItem name="SomeElement3" />
    </property>
  </xsl:template>

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

Но вам нужно указать, куда вы хотите поместить его в атрибуте соответствия шаблона.

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