Home > Net >  XSLT value-of ignores tags inside the element
XSLT value-of ignores tags inside the element

Time:12-07

I have an XML file with the following structure

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <card>
        <k>аванс</k>
        <body>
            <blockquote>аванс.</blockquote>
        </body>
    </card>
    <card>
        <k>авансыла-</k>
        <body>
            <blockquote>авансировать;</blockquote>
            <blockquote>авансылап авансом.</blockquote>
        </body>
    </card>
    <card>
        <k>авансылоо</k>
        <body>
            <blockquote>и. д. от авансыла-</blockquote>
            <blockquote>авансирование.</blockquote>
        </body>
    </card>
</root>

And I'm trying to sort all the cards by its k value with this XSL

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<root>
  <xsl:for-each select="root/card">
    <xsl:sort select="upper-case(k)" lang="ru"/>
      <k><xsl:value-of select="k"/></k>
      <body><xsl:value-of select="body"/></body>
  </xsl:for-each>
</root>
</xsl:template>

</xsl:stylesheet>

And now the funny part: in online XSL editors, everything works fine and as expected. But because the XML file is quite big and I can't upload it, I had to download Oxygen XML Editor, and its output is a bit different. For some reason, Oxygen removes all <blockquote> tags and I can't understand why. How can I keep <blockquote> tags in my final XML?

CodePudding user response:

Please try the following XSLT.

I am using Saxon XSLT processor v.9.7.0.15

Input XML

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <card>
        <k>авансыла-</k>
        <body>
            <blockquote>авансировать;</blockquote>
            <blockquote>авансылап авансом.</blockquote>
        </body>
    </card>
    <card>
        <k>авансылоо</k>
        <body>
            <blockquote>и. д. от авансыла-</blockquote>
            <blockquote>авансирование.</blockquote>
        </body>
    </card>
    <card>
        <k>аванс</k>
        <body>
            <blockquote>аванс.</blockquote>
        </body>
    </card>
</root>

XSLT

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

    <xsl:template match="/root">
        <root>
            <xsl:for-each select="card">
                <xsl:sort select="upper-case(k)" lang="ru"/>
                    <xsl:copy-of select="."/>
            </xsl:for-each>
        </root>
    </xsl:template>
</xsl:stylesheet>

Output

<?xml version='1.0' encoding='utf-8' ?>
<root>
  <card>
    <k>аванс</k>
    <body>
      <blockquote>аванс.</blockquote>
    </body>
  </card>
  <card>
    <k>авансыла-</k>
    <body>
      <blockquote>авансировать;</blockquote>
      <blockquote>авансылап авансом.</blockquote>
    </body>
  </card>
  <card>
    <k>авансылоо</k>
    <body>
      <blockquote>и. д. от авансыла-</blockquote>
      <blockquote>авансирование.</blockquote>
    </body>
  </card>
</root>

CodePudding user response:

If (as it seems) you are using a processor that supports XSLT 2.0 then you can do simply:

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

<xsl:template match="/root">
    <xsl:copy>
        <xsl:perform-sort select="card">
            <xsl:sort select="upper-case(k)" lang="ru"/>
        </xsl:perform-sort> 
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
  • Related