Home > Enterprise >  XSLT 1.0 transform some nodes on the same level, leave others intact
XSLT 1.0 transform some nodes on the same level, leave others intact

Time:03-21

The problem that I am facing is, how to select some nodes that are on the same level as other different nodes and to sort just them and leave others intact. I've tried to match those by using template match, but can't figure out how to sort all of them without selecting any of descendants (for-each and apply-templates requires select...)

I have the following XML

<RootNode>
    <actionOverrides>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <formFactor>Small</formFactor>
        <type>Page</type>
    </actionOverrides>
    <actionOverrides>
        <formFactor>Large</formFactor>
        <type>Page</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>View</actionName>
        <type>Default</type>
    </actionOverrides>
    <deprecated>false</deprecated>
    <somethingElse>false</somethingElse>
</RootNode>

I need sorting of certain subnodes (based on subnode's subnode value) --> sort actionOverrides where type = 'Page', sorted by formFactor

<RootNode>
    <actionOverrides>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <formFactor>Large</formFactor>
        <type>Page</type>
    </actionOverrides>
    <actionOverrides>
        <formFactor>Small</formFactor>
        <type>Page</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>View</actionName>
        <type>Default</type>
    </actionOverrides>
    <deprecated>false</deprecated>
    <somethingElse>false</somethingElse>
</RootNode>

I've tried with something like this, but this gives me duplicates.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://soap.sforce.com/2006/04/metadata">
    <xsl:output method="xml" indent="yes"/>
    <!-- XSLT identity transformation -->
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="/RootNode/actionOverrides[type='Page']">
        <xsl:for-each select="../actionOverrides[type='Page']">
            <xsl:sort select="formFactor" order="ascending"/>
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

CodePudding user response:

Here's one way you could look at it:

XSLT 1.0

<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:strip-space elements="*"/>

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

<xsl:template match="/RootNode">
    <xsl:copy>
        <xsl:apply-templates select="actionOverrides[type='Page'][1]/preceding-sibling::*"/>
        <xsl:apply-templates select="actionOverrides[type='Page']">
            <xsl:sort select="formFactor"/>
        </xsl:apply-templates>
        <xsl:apply-templates select="actionOverrides[type='Page'][last()]/following-sibling::*"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
  • Related