1

I have a XSLT that transforms XML input into JSON, however I have a problem when one of the group-by has empty values. In a nutshell I'm transposing a key/value pair and pivoting the data out so I can insert it into a DB. My problem is @TableName is in some cases empty, (which cause errounous commas in the JSON output) and I need to bypass them, the problem is I can't get position() and last() because they don't contain accurate values because of the empty TableName. I've tried using group-starting-with, but I can't get the syntax right. I'm open to suggestions. Sample XML input into the XSLT

<root xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <Metric measType="1526727077"
           measResult="0"
           endTime="2016-08-25T04:30:00-07:00"
           measObjLdn="LTHBC0126858/HANS:Board Type=MPT, Cabinet No.=0, Subrack No.=1, Slot No.=7"
           Element_Type="ENODEB"
           Key1="LTHBC0126858"
           TableName=""
           ColumnName=""/>
   <Metric measType="1526727075"
           measResult="0"
           endTime="2016-08-25T04:30:00-07:00"
           measObjLdn="LTHBC0126858/GTPU:Board Type=MPT, Cabinet No.=0, Subrack No.=1, Slot No.=7"
           Element_Type="ENODEB"
           Key1="LTHBC0126858"
           TableName="HH_ENODEB"
           ColumnName="H1526727075"
           H1526727075="0"/>
   <Metric measType="1526727076"
           measResult="0"
           endTime="2016-08-25T04:30:00-07:00"
           measObjLdn="LTHBC0126858/GTPU:Board Type=MPT, Cabinet No.=0, Subrack No.=1, Slot No.=7"
           Element_Type="ENODEB"
           Key1="LTHBC0126858"
           TableName="HH_ENODEB"
           ColumnName="H1526727076"
           H1526727076="0"/>
   <Metric measType="1526727077"
           measResult="0"
           endTime="2016-08-25T04:30:00-07:00"
           measObjLdn="LTHBC0126858/DIFF:Board Type=MPT, Cabinet No.=0, Subrack No.=1, Slot No.=7"
           Element_Type="ENODEB"
           Key1="LTHBC0126858"
           TableName="DIFF"
           ColumnName="H1526727077"
           H1526727077="0"/>
   <Metric measType="1526737817"
           measResult="0"
           endTime="2016-08-25T04:30:00-07:00"
           measObjLdn="LTHBC0126858/Board.Service:Board Type=BBP, Cabinet No.=0, Subrack No.=1, Slot No.=3"
           Element_Type="Unknown"
           Key1="Unknown"
           TableName=""/>
</root>

I have some bogus <TEXT> output in my XSLT for debugging purposes

<?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" version="2.0">
    <xsl:output method="text" encoding="utf-8"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="root">
        <xsl:text>{"root":{</xsl:text>
        <xsl:text>"Table":[</xsl:text>
        <xsl:for-each-group select="Metric" group-by="@measObjLdn">
            <xsl:sort select="current-grouping-key()"/>
            <xsl:variable name="curr_key" select="current-grouping-key()"/>
            <xsl:for-each-group select="current-group()" group-by="@TableName">
                <xsl:sort select="current-grouping-key()"/>
                <xsl:variable name="curr_table" select="current-grouping-key()"/>
            <xsl:text>Table</xsl:text>
            <xsl:value-of select="$curr_table"/>
                <xsl:if test="current-grouping-key() != ''">
                    <xsl:text>{"TableName":"</xsl:text>
                    <xsl:value-of select="current-grouping-key()"/>
                    <xsl:text>",</xsl:text>
                    <xsl:text>"Stamp":"</xsl:text>
                    <xsl:value-of select="@endTime"/>
                    <xsl:text>",</xsl:text>
                    <xsl:text>"measObjLdn":"</xsl:text>
                    <xsl:value-of select="$curr_key"/>
                    <xsl:text>",</xsl:text>
                    <xsl:text>"Element_Type":"</xsl:text>
                    <xsl:value-of select="@Element_Type"/>
                    <xsl:text>",</xsl:text>
                    <xsl:text>"Key1":"</xsl:text>
                    <xsl:value-of select="@Key1"/>
                    <xsl:text>"</xsl:text>
                    <xsl:for-each select="current-group()">
                        <xsl:for-each select="@*">
                            <xsl:if test="starts-with(name(), 'H')">
                                <xsl:text>,"</xsl:text>
                                <xsl:value-of select="name()"/>
                                <xsl:text>":"</xsl:text>
                                <xsl:value-of select="number(.)"/>
                                <xsl:text>"</xsl:text>
                            </xsl:if>
                        </xsl:for-each>
                    </xsl:for-each>
                    <xsl:text>}</xsl:text>
                </xsl:if>
            </xsl:for-each-group>
            <xsl:text>position</xsl:text>
            <xsl:value-of select="position()"/>
            <xsl:text>last</xsl:text>
            <xsl:value-of select="last()"/>
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each-group>
        <xsl:text>]}}</xsl:text>
    </xsl:template>
</xsl:stylesheet>
1
  • Can you edit your question to show the output you expect in this case? Thank you! Commented Sep 9, 2016 at 8:12

1 Answer 1

2

What you should do in this case, is have the conditional check for empty table names as part of the xsl:for-each-group, like so:

<xsl:for-each-group select="current-group()[@TableName!='']" group-by="@TableName">

position() will then work as you expect at it refers to the position of the node in the selected node set, not the position in the actual XML hierarchy.

Additionally, you should change the xsl:for-each-group on Metric elements too in a similar fashion

<xsl:for-each-group select="Metric[@TableName != '']" group-by="@measObjLdn">

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
    <xsl:output method="text" encoding="utf-8"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="root">
        <xsl:text>{"root":{</xsl:text>
        <xsl:text>"Table":[</xsl:text>
        <xsl:for-each-group select="Metric[@TableName != '']" group-by="@measObjLdn">
            <xsl:sort select="current-grouping-key()"/>
            <xsl:variable name="curr_key" select="current-grouping-key()"/>
            <xsl:for-each-group select="current-group()[@TableName!='']" group-by="@TableName">
                <xsl:sort select="current-grouping-key()"/>
                <xsl:variable name="curr_table" select="current-grouping-key()"/>
                <xsl:text>{"TableName":"</xsl:text>
                <xsl:value-of select="current-grouping-key()"/>
                <xsl:text>",</xsl:text>
                <xsl:text>"Stamp":"</xsl:text>
                <xsl:value-of select="@endTime"/>
                <xsl:text>",</xsl:text>
                <xsl:text>"measObjLdn":"</xsl:text>
                <xsl:value-of select="$curr_key"/>
                <xsl:text>",</xsl:text>
                <xsl:text>"Element_Type":"</xsl:text>
                <xsl:value-of select="@Element_Type"/>
                <xsl:text>",</xsl:text>
                <xsl:text>"Key1":"</xsl:text>
                <xsl:value-of select="@Key1"/>
                <xsl:text>"</xsl:text>
                <xsl:for-each select="current-group()">
                    <xsl:for-each select="@*">
                        <xsl:if test="starts-with(name(), 'H')">
                            <xsl:text>,"</xsl:text>
                            <xsl:value-of select="name()"/>
                            <xsl:text>":"</xsl:text>
                            <xsl:value-of select="number(.)"/>
                            <xsl:text>"</xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                </xsl:for-each>
                <xsl:text>}</xsl:text>
            </xsl:for-each-group>
            <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each-group>
        <xsl:text>]}}</xsl:text>
    </xsl:template>
</xsl:stylesheet>

This produces the following JSON

{
   "root":{
      "Table":[
         {
            "TableName":"DIFF",
            "Stamp":"2016-08-25T04:30:00-07:00",
            "measObjLdn":"LTHBC0126858/DIFF:Board Type=MPT, Cabinet No.=0, Subrack No.=1, Slot No.=7",
            "Element_Type":"ENODEB",
            "Key1":"LTHBC0126858",
            "H1526727077":"0"
         },
         {
            "TableName":"HH_ENODEB",
            "Stamp":"2016-08-25T04:30:00-07:00",
            "measObjLdn":"LTHBC0126858/GTPU:Board Type=MPT, Cabinet No.=0, Subrack No.=1, Slot No.=7",
            "Element_Type":"ENODEB",
            "Key1":"LTHBC0126858",
            "H1526727075":"0",
            "H1526727076":"0"
         }
      ]
   }
}
Sign up to request clarification or add additional context in comments.

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.