Reputation: 181
I want to convert my XML document but not sure whether the desired output can be obtained using XSLT. Below is my XML code:
<GetInvoiceList>
<Request>
<Case>
<id>Case_1</id>
<CaseID>Hi</CaseID>
</Case>
<BillStatusCode>
<BillStatusCode>type description</BillStatusCode>
<typecode>1</typecode>
</BillStatusCode>
<EBillProcessStatusCode>
<EBillProcessStatusCode>type description</EBillProcessStatusCode>
<typecode>2</typecode>
</EBillProcessStatusCode>
</Request>
</GetInvoiceList>
I want to convert it into this:
<GetInvoiceList>
<Request>
<Case id="Case_1">
<CaseID>Hi</CaseID>
</Case>
<BillStatusCode typecode="1">type description</BillStatusCode>
<EBillProcessStatusCode typecode="2">type description</EBillProcessStatusCode>
</Request>
</GetInvoiceList>
Is it possible to get the desired output? Would appreciate any help regarding this. Thanks!
Upvotes: 0
Views: 96
Reputation: 116959
If I understand correctly, the "generic solution" to undo the mess you have created would do two things:
Convert id
and typecode
elements to attributes of their parent element;
Eliminate any element whose name is the same as the name of its parent element, and copy its child nodes (text nodes in your example) to the parent element.
This translates to:
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:template match="*">
<xsl:copy>
<xsl:for-each select="id | typecode">
<xsl:attribute name="{name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates select="node()[not(self::id or self::typecode)]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name(.) = name(..)]">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 68
Try it!!!, now I've changed the coding based on the element position. If you change the element positions in the input this won't help you.
Regards Bala
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="all"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="all">
<xsl:choose>
<xsl:when test="(count(ancestor::*) = 3 and count(preceding::*) = 0)
or (count(ancestor::*) = 3 and count(preceding::*) > 1 and count(preceding-sibling::*) = 1)">
</xsl:when>
<xsl:when test="count(ancestor::*) = 3 and count(preceding-sibling::*) = 0">
<xsl:apply-templates mode="all"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:choose>
<xsl:when test="count(ancestor::*) = 2 and count(preceding-sibling::*) = 0">
<xsl:attribute name="{*[1]/name()}" select="*[1]"/>
</xsl:when>
<xsl:when test="count(ancestor::*) = 2 and count(preceding-sibling::*) != 0">
<xsl:attribute name="{*[2]/name()}" select="*[2]"/>
</xsl:when>
</xsl:choose>
<xsl:apply-templates mode="all"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0