Как создать новый список и пометить узлы в нем с помощью xslt - PullRequest
1 голос
/ 28 апреля 2011

Я преобразую XML в другой, используя Identity Transformation, и во время этого на основе условия я хочу пометить несколько узлов в новом списке.Предположим, у меня есть такой XML:

A
B

p1


p2


p3


p4


Из этого XML я хочу обновить имя 'nod' до 'newnod' и создать упорядоченный список для элемента 'c';так что вывод будет выглядеть так:

A
B
<заказ списка>

p1


p2


p3


p4



Может кто-нибудь сказать, пожалуйста, как это сделать.

Спасибо!!!

Ответы [ 4 ]

1 голос
/ 28 апреля 2011

Это дает желаемый результат для вашего примера:

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

  <xsl:output indent="yes"/>

  <xsl:template match="/nod">
    <newnod>
      <xsl:copy-of select="*[not( self::c )]"/>
      <orderedlist>
        <xsl:apply-templates select="c">
          <xsl:sort/>
        </xsl:apply-templates>
      </orderedlist>
    </newnod>
  </xsl:template>

  <xsl:template match="nod/c">
    <listitem>
      <xsl:copy-of select="node()"/>
    </listitem>
  </xsl:template>

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

</xsl:stylesheet>

Обратите внимание, что для вашего фактического ввода может потребоваться некоторая настройка.Например, детали сортировки.Или последовательность a, b и c.И смешать все c вместе или нет?Но это работает для вашего образца.

1 голос
/ 28 апреля 2011

Вот настоящее решение в стиле "push-style":

<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="/nod">
  <newnod>
   <xsl:apply-templates select="node()|@*"/>
  </newnod>
 </xsl:template>

 <xsl:template match="c[1]">
  <orderedlist>
   <xsl:apply-templates mode="wrap"
    select=".|following-sibling::c"/>
  </orderedlist>
 </xsl:template>

 <xsl:template match="c" mode="wrap">
  <listitem>
   <xsl:apply-templates/>
  </listitem>
 </xsl:template>

 <xsl:template match="c"/>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML :

<nod>
 <a>A</a>
 <b>B</b>
 <c><p>p1</p></c>
 <c><p>p2</p></c>
 <c><p>p3</p></c>
 <c><p>p4</p></c>
</nod>

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

<newnod>
  <a>A</a>
  <b>B</b>
  <orderedlist>
    <listitem>
      <p>p1</p>
    </listitem>
    <listitem>
      <p>p2</p>
    </listitem>
    <listitem>
      <p>p3</p>
    </listitem>
    <listitem>
      <p>p4</p>
    </listitem>
  </orderedlist>
</newnod>
0 голосов
/ 29 апреля 2011

Другой подход заключается в прохождении следующей оси следующим образом:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="nod">
        <newnod>
            <xsl:apply-templates select="node()[1]|@*"/>
        </newnod>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="c">
        <orderedlist>
            <xsl:call-template name="wrap"/>
        </orderedlist>
        <xsl:apply-templates select="following-sibling::node()[1]"
                             mode="search"/>
    </xsl:template>
    <xsl:template match="c" name="wrap" mode="wrap">
        <listitem>
            <xsl:apply-templates select="node()[1]|@*"/>
        </listitem>
        <xsl:apply-templates select="following-sibling::node()[1]"
                             mode="wrap"/>
    </xsl:template>
    <xsl:template match="node()" mode="wrap"/>
    <xsl:template match="c" mode="search">
        <xsl:apply-templates select="following-sibling::node()[1]"
                             mode="search"/>
    </xsl:template>
    <xsl:template match="node()" mode="search">
        <xsl:apply-templates select="."/>
    </xsl:template>
</xsl:stylesheet>

или короче (больше "стиль нажатия"):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()[1]|@*"/>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="nod">
        <newnod>
            <xsl:apply-templates select="node()[1]|@*"/>
        </newnod>
        <xsl:apply-templates select="following-sibling::node()[1]"/>
    </xsl:template>
    <xsl:template match="c">
        <orderedlist>
            <xsl:call-template name="wrap"/>
        </orderedlist>
        <xsl:apply-templates select="following-sibling::node()
                                        [not(self::c)][1]"/>
    </xsl:template>
    <xsl:template match="c" name="wrap" mode="wrap">
        <listitem>
            <xsl:apply-templates select="node()[1]|@*"/>
        </listitem>
        <xsl:apply-templates select="following-sibling::node()[1]
                                        /self::c"
                             mode="wrap"/>
    </xsl:template>
</xsl:stylesheet>

Оба выхода:

<newnod>
    <a>A</a>
    <b>B</b>
    <orderedlist>
        <listitem>
            <p>p1</p>
        </listitem>
        <listitem>
            <p>p2</p>
        </listitem>
        <listitem>
            <p>p3</p>
        </listitem>
        <listitem>
            <p>p4</p>
        </listitem>
    </orderedlist>
</newnod>

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

0 голосов
/ 28 апреля 2011

Вы можете использовать что-то вроде:

<xsl:template match="nod">
    <newnod>
        <xsl:copy-of select="a"/>
        <xsl:copy-of select="b"/>
        <orderedlist>
            <xsl:for-each select="c">
                <listitem><p><xsl:value-of select="."/></p></listitem>
            </xsl:for-each>
        </orderedlist>
    </newnod>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...