简体   繁体   中英

Create one attribute “stats” in JSON from XML containing multiple attributes “stats” in XSLT 1.0

I have an XML input with elements that have a number of attributes named "stats".

I'd like to create just one attribute element "stats" for each of the existing attributes and put it in JSON as one key.

Input:

<STATS>
    <CODE>Apple</CODE><COUNT>4</COUNT>
</STATS>
<STATS>
    <CODE>Orange</CODE><COUNT>1876</COUNT>
</STATS>
<STATS>
    <CODE>Kiwi</CODE><COUNT>9</COUNT>
</STATS>

Output:

"STATS":{
    "Apple":4,
    "Orange":1876,
    "Kiwi": 9
}

UPDATE: I've tried this XSL

<?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>&quot;</xsl:text><xsl:value-of select="."/><xsl:text>&quot;</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>

But this doesn't work, it seems. It is giving me the following output:

    "STATS" :{

    "CODE" :"Apple",
    "COUNT" :"4"
            },
    "STATS" :{

    "CODE" :"Orange",
    "COUNT" :"1876"
            },
    "STATS" :{

    "CODE" :"Kiwi",
    "COUNT" :"9"
            }

What's the right way to do this?

Given a well-formed (!) input such as:

XML

<root>
    <STATS>
        <CODE>Apple</CODE>
        <COUNT>4</COUNT>
    </STATS>
    <STATS>
        <CODE>Orange</CODE>
        <COUNT>1876</COUNT>
    </STATS>
    <STATS>
        <CODE>Kiwi</CODE>
        <COUNT>9</COUNT>
    </STATS>
</root>

the following stylesheet:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>

<xsl:template match="/root">
    <xsl:text>"STATS":{</xsl:text>
    <xsl:for-each select="STATS">
        <xsl:text>"</xsl:text>
        <xsl:value-of select="CODE"/>
        <xsl:text>":</xsl:text>
        <xsl:value-of select="COUNT"/>
        <xsl:if test="position()!=last()">,</xsl:if>
    </xsl:for-each>
    <xsl:text>}</xsl:text>
</xsl:template>

</xsl:stylesheet>

wil return:

Result

"STATS":{"Apple":4,"Orange":1876,"Kiwi":9}

One possibility to achieve this JSON output is the following XSLT-1.0 code. It does assume that your input XML is wrapped in an element named root to make it well-formed .

So the input XML file looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <STATS>
        <CODE>Apple</CODE><COUNT>4</COUNT>
    </STATS>
    <STATS>
        <CODE>Orange</CODE><COUNT>1876</COUNT>
    </STATS>
    <STATS>
        <CODE>Kiwi</CODE><COUNT>9</COUNT>
    </STATS>
</root>

The XSLT-1.0 file satisfying your needs looks like this:

<?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="/root">
    <xsl:text>STATS: {&#xa;</xsl:text>
        <xsl:apply-templates select="STATS" />
    <xsl:text>&#xa;}</xsl:text>
</xsl:template>

<!-- STATS elements -->
<xsl:template match="STATS">
    <xsl:text>  "</xsl:text><xsl:value-of select="CODE"/><xsl:text>": </xsl:text>
    <xsl:value-of select="COUNT"/>
    <xsl:if test="position() != last()"><xsl:text>,&#xa;</xsl:text></xsl:if>
</xsl:template>

</xsl:stylesheet>

Its output is:

STATS: {
  "Apple": 4,
  "Orange": 1876,
  "Kiwi": 9
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM