XSLT: copy all XML except where the attribute contains a value

purpose

I would like to copy all of the XML except where the attribute value contains a specific character, in this case .

. Where .

exists, remove the element that has this attribute and all of its children. I'm new to xslt and reading a bit, but I can't seem to find a way to capture the parent + all of its children.

Current XSL

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


<xsl:template match="@* | node()">

        <xsl:copy>

            <xsl:apply-templates select="@* | node()" />

        </xsl:copy>

</xsl:template>

<xsl:template match="descendant-or-self::root/*/@name[contains(., '.')]" />

      

XML example

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <complexType name="tableData2File">
        <complexContent>
            <extension base="taskElement">
                <sequence>
                    <element name="source" type="tableData2File.source" />
                    <element name="parser" type="parser" />
                    <element name="target" type="node.uri" />
                </sequence>
                <attribute name="addNewColumns" type="minlength" use="optional" />                              
            </extension>
        </complexContent>
    </complexType>

    <!-- 
    match idViolationsCount.test,
    then remove all its content
     -->
    <complexType name="idViolationsCount.test">
        <complexContent>
            <extension base="tableTask">
                <sequence>
                    <element name="index" type="columnsNoAs" minOccurs="1" />
                    <element name="condition" type="stringWithRef" minOccurs="0" />
                    <element name="allowExpressions" type="boolWithRef" minOccurs="0" />
                </sequence>
                <attribute name="mode" type="mergeMode" use="required" />
            </extension>
        </complexContent>
    </complexType>

</root>

      

Desired output XML

<root>
    <complexType name="tableData2File">
        <complexContent>
            <extension base="taskElement">
                <sequence>
                    <element name="source" type="tableData2File.source" />
                    <element name="parser" type="parser" />
                    <element name="target" type="node.uri" />
                </sequence>
                <attribute name="addNewColumns" type="minlength" use="optional" />                              
            </extension>
        </complexContent>
    </complexType>

    <!-- no idViolationsCount.test! --> 
</root>

      

+3


source to share


1 answer


This looks like the correct approach (identity pattern overridden for the thing you want to remove), but you cannot use descendant-or-self::

in the match pattern. However, you don't need to, just

<xsl:template match="root/*[contains(@name, '.')]" />

      

should do the job. Note that your original matching pattern root/*/@name[contains(., '.')]

will match the name

node attribute , not the element that hosts it, so you will eventually remove the attribute, but leave that element intact.



You don't need to do anything special with the children of the removed element - this empty template will remove the entire element including its content, if you only want to remove this element but keep its descendants, then you need a different template

<xsl:template match="root/*[contains(@name, '.')]">
  <!-- don't output anything now, but keep processing children -->
  <xsl:apply-templates />
</xsl:template>

      

+6


source







All Articles