2

I'm trying to remove the node which contains (Descriptor=ID1) but it returns below error.

XML

<?xml version='1.0' encoding='UTF-8'?>
<Data>
    <Entry>
        <Line>1</Line>
        <Reference Descriptor="ID1">
            <ID type="ID">gbgfdbnfg</ID>
        </Reference>
        <Reference Descriptor="ID2">
            <ID type="ID">tshbtdsg</ID>
        </Reference>
        <Reference Descriptor="ID3">
            <ID type="ID">rhbdgb</ID>
        </Reference>
    </Entry>
</Data>

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="*[contains(Reference/@Descriptor,'ID1')]">
        <!-- Do nothing -->
    </xsl:template>
    
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template> 
</xsl:stylesheet>

Error:

A sequence of more than one item is not allowed as the first argument of fn:contains() ("ID1", "ID2")

Expected Output:

<?xml version='1.0' encoding='UTF-8'?>
<Data>
    <Entry>
        <Line>1</Line>
        <Reference Descriptor="ID2">
            <ID type="ID">tshbtdsg</ID>
        </Reference>
        <Reference Descriptor="ID3">
            <ID type="ID">rhbdgb</ID>
        </Reference>
    </Entry>
</Data>
kjhughes
  • 106,133
  • 27
  • 181
  • 240
user9324800
  • 173
  • 2
  • 10

1 Answers1

2

Change

<xsl:template match="*[contains(Reference/@Descriptor,'ID1')]">

to

<xsl:template match="Reference[@Descriptor='ID1']">

because

  • It's Reference elements with the targeted Descriptor attribute values that you wish to omit, not parents of Reference elements.
  • You want an equality check, not a substring containment check, of the value of the Descriptor attribute.

See also


Update per follow-up asking about a true substring test need...

What if it contains <Reference Descriptor="Name: ID1"> and <Reference Descriptor="Item: ID2"> and <Reference Descriptor="Book: ID3"> and I would like to remove node which contains 'Name'

Then use this XPath to avoid the error caused by giving contains() a node set or sequence as its first argument:

<xsl:template match="Reference[@Descriptor[contains(.,'Name')]]">

Note that starts-with() could be used instead of contains().

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • Thank you. What if it contains and and and I would like to remove node which contains 'Name' – user9324800 Mar 11 '23 at 01:33
  • Answer updated to show how to test for a substring of the `Descriptor` attribute value while avoiding the original error. – kjhughes Mar 11 '23 at 01:41