Given below is my XML input. How do I copy or match selected elements that I want to reflect in my XML output using XSL.
The general idea of the logic should be to specify only the elements I am interested instead of specifying the elements that I don’t like to be included in the output. The elements that I want to reflect in my output XML are always present in the XML Inpput. The rest of the elements vary depending on what the system has generated and so I cannot just specify what to remove.
I was able to this without the namespace from the input by doing the copy-of, but when the namespace is present the code is not working.
I found a way to remove the namespace but when combined with the copy-of, didn’t work as well. I am quite confused as to how XSL behaves.
Please bear with my inquiry, I’m very new to XML and XSL and I was assigned to this task because no one from our team had the experience working with XML. Thank you in advance.
XML Input:
<Transaction xmlns="http://www.test.com/rdc.xsd">
<Transaction>
<StoreName id="aa">STORE A</StoreName>
<TransNo>TXN0001</TransNo>
<RegisterNo>REG001</RegisterNo>
<Items>
<Item id="1">
<ItemID>A001</ItemID>
<ItemDesc>Keychain</ItemDesc>
</Item>
<Item id="2">
<ItemID>A002</ItemID>
<ItemDesc>Wallet</ItemDesc>
</Item>
</Items>
<IDONTLIKETHIS_1>
<STOREXXX>XXX</STOREXXX>
<TRANSXXX>YYY</TRANSXXX>
</IDONTLIKETHIS_1>
<IDONTLIKETHIS_2>
<STOREXXX>XXX</STOREXXX>
<TRANSXXX>YYY</TRANSXXX>
</IDONTLIKETHIS_2>
</Transaction>
</Transaction>
Desired Output:
<Transaction>
<Transaction>
<StoreName id="aa">STORE A</StoreName>
<TransNo>TXN0001</TransNo>
<RegisterNo>REG001</RegisterNo>
<Items>
<Item id="1">
<ItemID>A001</ItemID>
<ItemDesc>Keychain</ItemDesc>
</Item>
<Item id="2">
<ItemID>A002</ItemID>
<ItemDesc>Wallet</ItemDesc>
</Item>
</Items>
</Transaction>
</Transaction>
I’ve tried the code below but the problem with it is that I’m missing the second Transaction element and the xmlns attribute is present in the root element:
<xsl:template match="*">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="node()[not(self::*)]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="x:Transaction/x:StoreName"/>
<xsl:copy-of select="x:Transaction/x:TransNo"/>
<xsl:copy-of select="x:Transaction/x:RegisterNo"/>
<xsl:copy-of select="x:Transaction/x:Items"/>
</xsl:copy>
</xsl:template>
This transformation uses a list of all names of elements that we want to copy after processing:
when applied to the provided XML document:
the wanted, correct result is produced:
Do note: One advantage of this solution over other possible solution is that the string containing the pipe-delimited list of element names can be provide as an externally-specified parameter to the transformation, making it very powerful and flexible and eliminating the need to alter the code any time we include new elements (or exclude some) from our white-list.