In this sample XML I want to match app
elements where the text in the indexInfo
element does not match the same text from the z_app
element with the same name.
Since the indexInfo
element from appname2
and z_appname2
both match then I don't want to include these. In this case I would only want app elements appname1
and z_appname1
returned since their indexInfo
content is different.
I'm looking for a match expression that I can use for an XSLT template.
<root>
<app name="appname1">
<indexInfo>
This is the text for the indexes
</indexInfo>
</app>
<app name="z_appname1">
<indexInfo>
This is the text for the indexes
But slightly different
</indexInfo>
</app>
<app name="appname2">
<indexInfo>
This is the text for the indexes
</indexInfo>
</app>
<app name="z_appname2">
<indexInfo>
This is the text for the indexes
</indexInfo>
</app>
</root>
Desired output:
<root>
<app name="appname1">
<indexInfo>
This is the text for the indexes
</indexInfo>
</app>
<app name="z_appname1">
<indexInfo>
This is the text for the indexes
But slightly different
</indexInfo>
</app>
</root>
CodePudding user response:
You could use xsl:key
to create a map matching all of the app
elements, using the value of @name
after "appname" and the value of the indexInfo
as the lookup key.
Then, in a template match expression, apply a predicate to match any app
in which selecting items by that key has more than one item, use an empty template to exclude that matching app
from the output:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="app" match="app" use="concat(substring-after(@name, 'appname'), '|', indexInfo)"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="app[key('app', concat(substring-after(@name, 'appname'), '|', indexInfo))[2]]"/>
</xsl:stylesheet>
CodePudding user response:
I'd do it this way:
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="*"/>
<xsl:key name="app-by-name" match="app" use="@name" />
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="app[starts-with(@name, 'z_')]">
<xsl:variable name="peer" select="key('app-by-name', substring-after(@name, 'z_'))" />
<xsl:if test="indexInfo != $peer/indexInfo">
<xsl:copy-of select=". | $peer"/>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>