I have a XML which have two parent nodes (Base, Sub). I need to write a XSLT to get the values for below condition.
Condition: Need to get different elements in both parents.
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Base>
<Student_ID>1234</Student_ID>
<Student_ID>1267</Student_ID>
<Student_ID>1890</Student_ID>
<Student_ID>5678</Student_ID>
<Student_ID>6743</Student_ID>
<Student_ID>8743</Student_ID>
</Base>
<Sub>
<Student_ID>5678</Student_ID>
<Student_ID>6743</Student_ID>
<Student_ID>3226</Student_ID>
<Student_ID>8123</Student_ID>
</Sub>
</Data>
Expected Output:
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<Student_ID>1234</Student_ID>
<Student_ID>1267</Student_ID>
<Student_ID>1890</Student_ID>
<Student_ID>8743</Student_ID>
<Student_ID>3226</Student_ID>
<Student_ID>8123</Student_ID>
</Data>
In XSLT 3 you could also consider xsl:merge
, that would allow you to handle duplicates in each branch; drawback is that merging requires sorting input sequences on merge key(s) so the result of
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
expand-text="yes"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Data">
<xsl:copy>
<xsl:merge>
<xsl:merge-source name="base" select="Base/Student_ID" sort-before-merge="yes">
<xsl:merge-key select="."/>
</xsl:merge-source>
<xsl:merge-source name="sub" select="Sub/Student_ID" sort-before-merge="yes">
<xsl:merge-key select="."/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:if test="count(current-merge-group('base')) = 0 and count(current-merge-group('sub')) = 1 or count(current-merge-group('base')) = 1 and count(current-merge-group('sub')) = 0">
<xsl:copy-of select="current-merge-group()"/>
</xsl:if>
</xsl:merge-action>
</xsl:merge>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
has the right elements but in sorted order:
<Data>
<Student_ID>1234</Student_ID>
<Student_ID>1267</Student_ID>
<Student_ID>1890</Student_ID>
<Student_ID>3226</Student_ID>
<Student_ID>8123</Student_ID>
<Student_ID>8743</Student_ID>
</Data>
Of course we could re-sort into original input order using
<xsl:template match="Data">
<xsl:copy>
<xsl:variable name="unique-ids" as="element(Student_ID)*">
<xsl:merge>
<xsl:merge-source name="base" select="Base/Student_ID" sort-before-merge="yes">
<xsl:merge-key select="."/>
</xsl:merge-source>
<xsl:merge-source name="sub" select="Sub/Student_ID" sort-before-merge="yes">
<xsl:merge-key select="."/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:if test="count(current-merge-group('base')) = 0 and count(current-merge-group('sub')) = 1 or count(current-merge-group('base')) = 1 and count(current-merge-group('sub')) = 0">
<xsl:sequence select="current-merge-group()"/>
</xsl:if>
</xsl:merge-action>
</xsl:merge>
</xsl:variable>
<xsl:copy-of select="$unique-ids/."/>
</xsl:copy>
</xsl:template>