Reputation: 658
I have an XML file that I would like to convert it to JSON with using XSLT. And I would like to manipulate property names of output JSON inside XSLT. But I could not manage to do that. Here is what I tried... I have following XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="xslt-trial.xsl"?>
<Invoice
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:AccountingCost>Cost Center</cbc:AccountingCost>
<cbc:BuyerReference>Buyer reference</cbc:BuyerReference>
<cac:InvoicePeriod>
<cbc:StartDate>2020-02-11</cbc:StartDate>
<cbc:EndDate>2020-02-21</cbc:EndDate>
</cac:InvoicePeriod>
<cac:ContractDocumentReference>
<cbc:ID>Agreement Id</cbc:ID>
</cac:ContractDocumentReference>
</Invoice>
and "xslt-trial.xsl" is:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">{
<xsl:apply-templates select="*"/>}
</xsl:template>
<!-- Object or Element Property-->
<xsl:template match="*">
"<xsl:value-of select="name()"/>" :<xsl:call-template name="Properties">
<xsl:with-param name="parent" select="'Yes'"> </xsl:with-param>
</xsl:call-template>
</xsl:template>
<!-- Array Element -->
<xsl:template match="*" mode="ArrayElement">
<xsl:call-template name="Properties"/>
</xsl:template>
<!-- Object Properties -->
<xsl:template name="Properties">
<xsl:param name="parent"></xsl:param>
<xsl:variable name="childName" select="name(*[1])"/>
<xsl:choose>
<xsl:when test="not(*|@*)"><xsl:choose><xsl:when test="$parent='Yes'"> <xsl:text>"</xsl:text><xsl:value-of select="."/><xsl:text>"</xsl:text></xsl:when>
<xsl:otherwise>"<xsl:value-of select="name()"/>":"<xsl:value-of select="."/>"</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="count(*[name()=$childName]) > 1">{ "<xsl:value-of select="$childName"/>" :[<xsl:apply-templates select="*" mode="ArrayElement"/>] }</xsl:when>
<xsl:otherwise>{
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="*"/>
}</xsl:otherwise>
</xsl:choose>
<xsl:if test="following-sibling::*">,</xsl:if>
</xsl:template>
<!-- Attribute Property -->
<xsl:template match="@*">"<xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>",
</xsl:template>
</xsl:stylesheet>
I get this output from Edge browser:
{
"Invoice" :{
"cbc:AccountingCost" :"Cost Center",
"cbc:BuyerReference" :"Buyer reference",
"cac:InvoicePeriod" :{
"cbc:StartDate" :"2020-02-11",
"cbc:EndDate" :"2020-02-21"
},
"cac:ContractDocumentReference" :{
"cbc:ID" :"Agreement Id"
}
}}
What I want to get is:
{
"Invoice" :{
"AccountingCost" :"Cost Center",
"BuyerReference" :"Buyer reference",
"InvoicePeriod" :{
"StartDate" :"2020-02-11",
"EndDate" :"2020-02-21"
},
"ContractDocumentReference" :{
"ID" :"Agreement Id"
}
}}
As you can see, I would like to remove "cac:" and "cbc:" from property names. But I cannot manage to filter these values out.
Does anybody have a suggestion?
Upvotes: 0
Views: 174
Reputation: 167716
If you use the function local-name()
instead of the function name()
then you should get element names without prefixes.
Upvotes: 1