11

XSLT eliminates parents' children dynamically

 4 years ago
source link: https://www.codesd.com/item/xslt-eliminates-parents-children-dynamically.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

XSLT eliminates parents' children dynamically

advertisements

To avoid having to hard code the child element names I want to remove, I'd like to make a dynamic process to remove child elements when a matching parent element name is found.

My XML file:

<A>
    <B1>
        <C>C</C>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <MOD>
            <C>C</C>
            <D>D</D>
            <E>E</E>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B1>
    <B2>
        <C>C</C>
        <E>E</E>
        <H>H</H>
        <MOD>
            <C>C</C>
            <D>D</D>
            <E>E</E>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B2>
    <B3>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <X>X</X>
        <MOD>
            <C>C</C>
            <D>D</D>
            <E>E</E>
            <F>F</F>
            <G>G</G>
            <X>G</X>
        </MOD>
    </B3>
</A>

Desired output:

My XML file:

<A>
    <B1>
        <C>C</C>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <MOD>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B1>
    <B2>
        <C>C</C>
        <E>E</E>
        <H>H</H>
        <MOD>
            <D>D</D>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B2>
    <B3>
        <D>D</D>
        <E>E</E>
        <H>H</H>
        <X>X</X>
        <MOD>
            <C>C</C>
            <F>F</F>
            <G>G</G>
        </MOD>
    </B3>
</A>

My XSLT

     <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
            exclude-result-prefixes="xs">
    <xsl:strip-space elements="*"/>
    <!-- copy all nodes -->
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <!-- Remove child elements but keep parent element with same name -->
    <xsl:template match="C[../ancestor::*/C]"/>
    <xsl:template match="D[../ancestor::*/D]"/>
    <xsl:template match="E[../ancestor::*/E]"/>
</xsl:stylesheet>

I think I can combine the remove element code like this

<xsl:template match="C|D|E[../ancestor::*/C|D|E]"/>

I'm not sure how to start, but I'm thinking the process would have to get the parent node names (C,D,E,H), cycle through the children comparing the parent node name to each child node name. When a match is found, remove the child element. Thanks.


As far as I can tell, this stylesheet does what you need. It produces output matching what you say you need by excluding elements that have a parent with a preceding sibling of the same name.

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

  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="*">
    <xsl:if test="not(parent::*/preceding-sibling::*[name() = name(current())])">
      <xsl:copy>
        <xsl:apply-templates/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

Tags xslt

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK