0

I'm using XSLT 3.0 to transform this document JSON to this document XML with the function json-to-xml,

<xsl:variable name="input-as-xml" select="json-to-xml(.)"/>

From saxon I pass this json like document XML:

String XML = "<root>" + JSON + "</root>";

I get an XML when call the function json-to-xml:

<?xml version="1.0" encoding="utf-8"?>
<map
    xmlns="http://www.w3.org/2005/xpath-functions">
    <string key="_D">urn:oasis:names:specification:ubl:schema:xsd:Invoice-2</string>
    <string key="_S">urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2</string>
    <string key="_B">urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2</string>
    <array key="Invoice">
        <map>
            <array key="ID">
                <map>
                    <string key="IdentifierContent">123</string>
                </map>
            </array>
            <array key="IssueDate">
                <map>
                    <string key="DateContent">2011-09-22</string>
                </map>
            </array>
            <array key="InvoicePeriod">
                <map>
                    <array key="StartDate">
                        <map>
                            <string key="DateContent">2011-08-01</string>
                        </map>
                    </array>
                    <array key="EndDate">
                        <map>
                            <string key="DateContent">2011-08-31</string>
                        </map>
                    </array>
                </map>
            </array>
            <array key="AccountingSupplierParty">
                <map>
                    <array key="Party">
                        <map>
                            <array key="PartyName">
                                <map>
                                    <array key="Name">
                                        <map>
                                            <string key="TextContent">Custom Cotter Pins</string>
                                        </map>
                                    </array>
                                </map>
                            </array>
                        </map>
                    </array>
                </map>
            </array>
            <array key="AccountingCustomerParty">
                <map>
                    <array key="Party">
                        <map>
                            <array key="PartyName">
                                <map>
                                    <array key="Name">
                                        <map>
                                            <string key="TextContent">North American Veeblefetzer</string>
                                        </map>
                                    </array>
                                </map>
                            </array>
                        </map>
                    </array>
                </map>
            </array>
            <array key="LegalMonetaryTotal">
                <map>
                    <array key="PayableAmount">
                        <map>
                            <number key="AmountContent">100.00</number>
                            <string key="AmountCurrencyIdentifier">CAD</string>
                        </map>
                    </array>
                </map>
            </array>
            <array key="InvoiceLine">
                <map>
                    <array key="ID">
                        <map>
                            <string key="IdentifierContent">1</string>
                        </map>
                    </array>
                    <array key="LineExtensionAmount">
                        <map>
                            <number key="AmountContent">100.00</number>
                            <string key="AmountCurrencyIdentifier">CAD</string>
                        </map>
                    </array>
                    <array key="Item">
                        <map>
                            <array key="Description">
                                <map>
                                    <string key="TextContent">Cotter pin, MIL-SPEC</string>
                                </map>
                            </array>
                        </map>
                    </array>
                </map>
            </array>
        </map>
    </array>
</map>

Is it correct pass this XML as parameter?

<xsl:apply-templates select="$input-as-xml" />

Please, any suggestion in how can I use templates to transform the XML that I want? I just want some suggestions.

2 Answers 2

2

The information about prefixes does not seem to be included in the JSON so I have decided to declare them as parameters and I have assumed you know the name/key of the element to start with (e.g. Invoice):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    exclude-result-prefixes="xs math fn"
    version="3.0">

    <xsl:param name="json-input" as="xs:string">{"_D":"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
        "_S":"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2",
        "_B":"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",
        "Invoice":[{
        "ID":[{"IdentifierContent":"123"}],
        "IssueDate":[{"DateContent":"2011-09-22"}],
        "InvoicePeriod":[{
        "StartDate":[{"DateContent":"2011-08-01"}],
        "EndDate":[{"DateContent":"2011-08-31"}]
        }],
        "AccountingSupplierParty":[{
        "Party":[{
        "PartyName":[{
        "Name":[{"TextContent":"Custom Cotter Pins"}]
        }]
        }]
        }],
        "AccountingCustomerParty":[{
        "Party":[{
        "PartyName":[{
        "Name":[{"TextContent":"North American Veeblefetzer"}]
        }]
        }]
        }],
        "LegalMonetaryTotal":[{
        "PayableAmount":[{"AmountContent":100.00,
        "AmountCurrencyIdentifier":"CAD"}]
        }],
        "InvoiceLine":[{
        "ID":[{"IdentifierContent":"1"}],
        "LineExtensionAmount":[{"AmountContent":100.00,
        "AmountCurrencyIdentifier":"CAD"}],
        "Item":[{
        "Description":[{"TextContent":"Cotter pin, MIL-SPEC"}]
        }]
        }]
        }]}</xsl:param>

    <xsl:param name="prefix2" as="xs:string" select="'cbc'"/>
    <xsl:param name="prefix1" as="xs:string" select="'cac'"/>

    <xsl:output indent="yes"/>

    <xsl:template name="xsl:initial-template">
        <xsl:apply-templates select="json-to-xml($json-input)//fn:array[@key = 'Invoice']"/>
    </xsl:template>

    <xsl:template match="fn:array[@key = 'Invoice']" priority="5">
        <xsl:variable name="ns" select="../fn:string[@key = '_D']"/>
        <xsl:variable name="ns1" select="../fn:string[@key = '_S']"/>
        <xsl:variable name="ns2" select="../fn:string[@key = '_B']"/>
        <xsl:element name="{@key}" namespace="{$ns}">
            <xsl:namespace name="{$prefix1}" select="$ns1"/>
            <xsl:namespace name="{$prefix2}" select="$ns2"/>
            <xsl:apply-templates>
                <xsl:with-param name="ns1" select="$ns1" tunnel="yes"/>
                <xsl:with-param name="ns2" select="$ns2" tunnel="yes"/>
            </xsl:apply-templates>
        </xsl:element>
    </xsl:template>

    <xsl:template match="fn:array[@key and *[1][self::fn:map[fn:string]] and not(*[2])]">
        <xsl:param name="ns2" tunnel="yes"/>
        <xsl:element name="{$prefix2}:{@key}" namespace="{$ns2}">
            <xsl:value-of select="fn:map/fn:string"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="fn:array[@key and fn:map[fn:array]]">
        <xsl:param name="ns1" tunnel="yes"/>
        <xsl:element name="{$prefix1}:{@key}" namespace="{$ns1}">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

2 Comments

This is the example that I was searching, it's clear and usefull although still have to put the attributes in the XML: <cbc:LineExtensionAmount currencyID="CAD">100.00</cbc:LineExtensionAmount>. Thank you Martin Honnen.
@Frankhuaylinosvelasquez, you should be able to extend the stylesheet by adding a template checking for the particular content of e.g. <number key="AmountContent">100.00</number> <string key="AmountCurrencyIdentifier">CAD</string> and then have it output the element with the attribute value.
0

JSON to XML Example:

JSON: "

"{\n" +"    \"color\": \"red\",\n" +" \"value\": \"#f00\"\n" +"}";

XSLT:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="jsonText"></xsl:param>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template name="init">
    <xsl:apply-templates select="json-to-xml($jsonText)"/>
</xsl:template>
<xsl:template match="string[@key = 'subjects']" xpath-default namespace="http://www.w3.org/2005/xpath-functions"><xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:sequence select="parse-xml(.)/node()"/></xsl:copy></xsl:template</xsl:stylesheet>`

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.