Search code examples
xsltxslt-1.0

Copy XML an Compare Node ID's if not match do not Copy the Node


An error message appears when testing the following XSLT.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:multimap="http://sap.com/xi/XI/SplitAndMerge" xmlns:n0="http://sap.com/xi/SAPGlobal20/Global">

  <!-- Definiere Variablen -->
  <xsl:variable name="ItemID" select="/multimap:Messages/multimap:Message1/n0:ServiceRequestFollowUpDocumentReplicationRequest/ServiceRequestFollowUpDocumentReplicateRequestMessage/ServiceRequest/Item/ID"/>
  <xsl:variable name="ServiceRequestItemID" select="/multimap:Messages/multimap:Message4/multimap:ServiceRequestItem"/>

  <!-- Kopiere das gesamte Dokument -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <!-- Überspringe ServiceRequestItem, deren ID nicht im ServiceRequest-Element ist -->
  <xsl:template match="multimap:ServiceRequestItem[not(ID = $ItemID)]"/>

</xsl:stylesheet>

And here is my XML:

<multimap:Messages xmlns:multimap="http://sap.com/xi/XI/SplitAndMerge">
    <multimap:Message1>
        <n0:ServiceRequestFollowUpDocumentReplicationRequest xmlns:n0="http://sap.com/xi/SAPGlobal20/Global" xmlns:prx="urn:sap.com:proxy:LV9">
            <ServiceRequestFollowUpDocumentReplicateRequestMessage>
                <ServiceRequest actionCode="01" itemListCompleteTransmissionIndicator="true">
                    <Item actionCode="01">
                        <ID>10</ID>
                    </Item>
                    <Item actionCode="01">
                        <ID>80</ID>
                    </Item>
                </ServiceRequest>
            </ServiceRequestFollowUpDocumentReplicateRequestMessage>
        </n0:ServiceRequestFollowUpDocumentReplicationRequest>
    </multimap:Message1>
    <multimap:Message4>
        <ServiceRequestItemCollection>
            <ServiceRequestItem>
                <ID>10</ID>
            </ServiceRequestItem>
            <ServiceRequestItem>
                <ID>80</ID>
            </ServiceRequestItem>
            <ServiceRequestItem>
                <ID>30</ID>
            </ServiceRequestItem>
        </ServiceRequestItemCollection>
    </multimap:Message4>
</multimap:Messages>

I want a copy of the XML, but nodes in ServiceRequestItem should only be copied if the ID is also included in the Item node.


Solution

  • You are getting an error because in XSLT 1.0 a match pattern is not allowed to reference a variable.

    You can avoid this elegantly and efficiently by using a key to resolve cross-references instead:

    XSLT 1.0

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:multimap="http://sap.com/xi/XI/SplitAndMerge" 
    xmlns:n0="http://sap.com/xi/SAPGlobal20/Global">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:key name="keepItems" match="n0:ServiceRequestFollowUpDocumentReplicationRequest/ServiceRequestFollowUpDocumentReplicateRequestMessage/ServiceRequest/Item" use="ID" />
    
    <!-- identity transform -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- Überspringe ServiceRequestItem, deren ID nicht im ServiceRequest-Element ist -->
    <xsl:template match="ServiceRequestItem[not(key('keepItems', ID))]"/>
    
    </xsl:stylesheet>