Convert xml to xml using xslt-encoded hierarchy xslt v1

In my XML input file, I have a coded hierarchy in the element attribute "lp":

<element lp="1"/>
<element lp="1.1"/>
<element lp="2"/>
<element lp="3"/>
<element lp="3.1" />
<element lp="3.2" />
<element lp="3.2.1" />

How to convert xml data to

<element lp="1">
   <element lp="1.1"/>
</element>
<element lp="2"/>
<element lp="3">
   <element lp="3.1"/>
   <element lp="3.2">
      <element lp="3.2.1">
   </element>
</element>
+3
source share
2 answers

There is probably an easy way to do this using XSLT2.0, but I assumed XSLT1.0 here.

One thing is not that your XML is not strictly true because it lacks a root element. For the purpose of the answer, I suggested that the root element is called elements

, , "" . , @lp. XSLT1.0 ,

<xsl:variable name="level" select="string-length(@lp) - string-length(translate(@lp, '.', ''))" />

, , ...

<xsl:apply-templates 
   select="element[string-length(@lp) - string-length(translate(@lp, '.', '')) = 0]"/>

<element lp="1."/>
<element lp="2."/>
<element lp="3."/>

, ,

  • @lp @lp

<xsl:apply-templates 
   select="following-sibling::element[substring(@lp, 1, $len) = $lp][string-length(@lp) - string-length(translate(@lp, '.', '')) = $level + 1]"/>

(. $len $level - , @lp )

, XSLT....

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

   <xsl:template match="/elements">
      <elements>
         <xsl:apply-templates select="element[string-length(@lp) - string-length(translate(@lp, '.', '')) = 0]"/>
      </elements>
   </xsl:template>

   <xsl:template match="element">
      <xsl:variable name="lp" select="@lp"/>
      <xsl:variable name="len" select="string-length(@lp)"/>
      <xsl:variable name="level" select="$len - string-length(translate(@lp, '.', ''))" />

      <xsl:copy>
         <xsl:copy-of select="@lp"/>
         <xsl:apply-templates select="following-sibling::element[substring(@lp, 1, $len) = $lp][string-length(@lp) - string-length(translate(@lp, '.', '')) = $level + 1]"/>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

XML

<elements>
    <element lp="1"/>
    <element lp="1.1"/>
    <element lp="2"/>
    <element lp="3"/>
    <element lp="3.1"/>
    <element lp="3.2"/>
    <element lp="3.2.1"/>
</elements>

<elements>
    <element lp="1">
        <element lp="1.1"/>
    </element>
    <element lp="2"/>
    <element lp="3">
        <element lp="3.1"/>
        <element lp="3.2">
            <element lp="3.2.1"/>
        </element>
    </element>
</elements>
+3

, ... :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="root">
        <result>
            <xsl:apply-templates select="element[not(contains(@lp,'.'))]"/>
        </result>
    </xsl:template>
    <xsl:template match="element">
    <xsl:variable name="vLevel" select="concat(@lp,'.')"/>
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates
                 select="../element[starts-with(@lp,$vLevel)]
                                   [not(contains(substring-after(@lp,$vLevel),
                                                 '.'))]"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

:

<result>
    <element lp="1">
        <element lp="1.1"></element>
    </element>
    <element lp="2"></element>
    <element lp="3">
        <element lp="3.1"></element>
        <element lp="3.2">
            <element lp="3.2.1"></element>
        </element>
    </element>
</result>
+3

Source: https://habr.com/ru/post/1781396/


All Articles