Расширенное преобразование XSLT для преобразования XML в XML - PullRequest
0 голосов
/ 25 апреля 2018

У меня есть XML, который выглядит следующим образом:

<root>
<name>
    <elements T="BI" S="1">1</elements>
    <elements T="BI" S="2">2</elements>
    <elements T="BI" S="3">3</elements>
</name>
<name>
    <elements T="BM" S="1">10</elements>
    <elements T="BM" S="2">20</elements>
    <elements T="BM" S="3">30</elements>
</name>
<name>
    <elements T="XX" S="1">001</elements>
    <elements T="XX" S="2">002</elements>
    <elements T="XX" S="3">003</elements>
</name>
<name>
    <elements T="XX" S="1">005</elements>
    <elements T="XX" S="2">007</elements>
    <elements T="XX" S="3">009</elements>
</name> </root>

, и я пытаюсь использовать следующее преобразование XSLT для преобразования этого XML в другой XML:

<xsl:for-each select="root">
<name_code_1>
    <xsl:for-each select="name">
        <xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
            <xsl:if test="@T = 'XX' and @S = '1'">
                <xsl:value-of select="substring(./text(),1,1000)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</name_code_1>
<name_code_2>
    <xsl:for-each select="name">
        <xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
            <xsl:if test="@T = 'XX' and @S = '2'">
                <xsl:value-of select="substring(./text(),1,1000)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</name_code_2>
<name_code_3>
    <xsl:for-each select="name">
        <xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
            <xsl:if test="@T = 'XX' and @S = '3'">
                <xsl:value-of select="substring(./text(),1,1000)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</name_code_3>
<name_code_4>
    <xsl:for-each select="name">
        <xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
            <xsl:if test="@T = 'XX' and @S = '1'">
                <xsl:value-of select="substring(./text(),1,1000)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</name_code_4>
<name_code_5>
    <xsl:for-each select="name">
        <xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
            <xsl:if test="@T = 'XX' and @S = '2'">
                <xsl:value-of select="substring(./text(),1,1000)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</name_code_5>
<name_code_6>
    <xsl:for-each select="name">
        <xsl:for-each select="element[not(@T=../preceding-sibling::*/element/@T)]">
            <xsl:if test="@T = 'XX' and @S = '3'">
                <xsl:value-of select="substring(./text(),1,1000)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</name_code_6> </xsl:for-each>

Я хочучтобы сгладить теги имен, где T-attribute = "XX" и на основе S-attribute = "1" или "2" и т. д. ..., заполните эти элементы в 6 различных тегов XML, как показано ниже. Вышеприведенная логика не работает .Может кто-нибудь, пожалуйста, помогите мне, предоставив некоторые предложения относительно того, как решить эту проблему.

Ниже приведен желаемый конечный результат:

<some_tag>
<name_code_1>001</name_code_1>
<name_code_2>002</name_code_2>
<name_code_3>003</name_code_3>
<name_code_4>005</name_code_4>
<name_code_5>007</name_code_5>
<name_code_6>009</name_code_6> </some_tag>

Спасибо, Qubiter

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Этот подход использует для каждой группы, и это лучший метод, если вы используете XSLT 2.0.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="root">
        <xsl:for-each-group select="name/elements" group-adjacent="if(@T='XX') then 'element' else 'cc'">
            <xsl:choose>
                <xsl:when test="current-grouping-key() = 'element'">
                    <some_tag>
                        <xsl:for-each select="current-group()">
                            <xsl:variable name="ss" select="position()"/>
                            <xsl:element name="{concat('name_code_', $ss)}">
                                <xsl:value-of select="."/>
                            </xsl:element>
                        </xsl:for-each>
                     </some_tag>
                </xsl:when>
                <xsl:otherwise></xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

Ниже выводится сгенерированный выше XSLT.

<?xml version="1.0" encoding="UTF-8"?>
<some_tag>
   <name_code_1>001</name_code_1>
   <name_code_2>002</name_code_2>
   <name_code_3>003</name_code_3>
   <name_code_4>005</name_code_4>
   <name_code_5>007</name_code_5>
   <name_code_6>009</name_code_6>
</some_tag>
0 голосов
/ 25 апреля 2018

Один из подходов - использование функции position() для получения индекса узла из подмножества elements узлов:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="text()" />                              <!-- remove superfluous text() nodes -->

  <xsl:template match="/root">                                 <!-- main match and creation of <some_tag> element -->
    <some_tag>
      <xsl:apply-templates select="name/elements[@T='XX']" />  <!-- create subset of nodes with attribute @T='XX' -->
    </some_tag>
  </xsl:template>

  <xsl:template match="elements">                              <!-- match elements from subset list -->
    <xsl:element name="{concat('name_code_',position())}">     <!-- concat position to node-name -->
      <xsl:value-of select="." />                              <!-- copy value -->
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

Вывод:

<some_tag>
    <name_code_1>001</name_code_1>
    <name_code_2>002</name_code_2>
    <name_code_3>003</name_code_3>
    <name_code_4>005</name_code_4>
    <name_code_5>007</name_code_5>
    <name_code_6>009</name_code_6>
</some_tag>
...