سؤال

I am new to xml xslt. i need to convert xml to specific format using xslt. need to look for similar tag names and convert them into specific format My input:

  <?xml version="1.0" encoding="UTF-8"?>
      <tpso xmlns="packetware:teleprovision" xmlns:xsi="http://www.w3.org/2001/XMLSchema-  instance" xsi:schemaLocation="tpso.xsd">
     <rollback>true</rollback>
        <soid>000027041866009@ALL</soid>
     <purpose>CHANGE</purpose>
       <description>tpso for Element ALL Action CHANGE</description>
       <failureAction>4</failureAction>
      <executeOnDate>2013-10-07T11:22:21.000+00:00</executeOnDate>
           <priority>8</priority>
           <subscriberID>260060059948580</subscriberID>
          <subscriberDN>48727554404</subscriberDN>
         <parameters>
           <parameter>
            <name>MSISDN</name>
           <value>48727554404</value>
       </parameter>
        </parameters>
           <serviceActions>

       <serviceAction>
                  <name>usage_state</name>
                <reference/>
             <parameters>
                     <parameter>
                        <name>action</name>
                          <value>add</value>
                   </parameter>
                    <parameter>
                      <name>old</name>
                 <value/>
                   </parameter>
                     <parameter>
                       <name>new</name>
                        <value>0ghfgfg</value>
                    </parameter>
                 </parameters>
             </serviceAction>

     <serviceAction>
        <name>usage_state</name>
        <reference/>
        <parameters>
            <parameter>
                <name>action</name>
                <value>add</value>
            </parameter>
            <parameter>
                <name>old</name>
                <value/>
            </parameter>
            <parameter>
                <name>new</name>
                <value>1ghfgfg</value>
            </parameter>
        </parameters>
    </serviceAction>

     <serviceAction>
        <name>usage_state</name>
        <reference/>
        <parameters>
            <parameter>
                <name>action</name>
                <value>add</value>
            </parameter>
            <parameter>
                <name>old</name>
                <value/>
            </parameter>
            <parameter>
                <name>new</name>
                <value>2ghfgfg</value>
            </parameter>
        </parameters>
    </serviceAction>

     <serviceAction>
        <name>usage_state</name>
        <reference/>
        <parameters>
            <parameter>
                <name>action</name>
                <value>add</value>
            </parameter>
            <parameter>
                <name>old</name>
                <value/>
            </parameter>
            <parameter>
                <name>new</name>
                <value>3ghfgfg</value>
            </parameter>
        </parameters>
    </serviceAction>
     <serviceAction>
        <name>usage_state</name>
        <reference/>
        <parameters>
            <parameter>
                <name>action</name>
                <value>add</value>
            </parameter>
            <parameter>
                <name>old</name>
                <value/>
            </parameter>
            <parameter>
                <name>new</name>
                <value>4ghfgfg</value>
            </parameter>
        </parameters>
    </serviceAction>
    </serviceActions>

        </tpso>

Output needs to be like below

           "usage_state": { "0" : {"operation": "add","value" : "0ghfgfg"},
                "1" : {"operation": "add","value" : "1ghfgfg"},
                "2" : {"operation": "add","value" : "2ghfgfg"},
                "3" : {"operation": "add","value" : "3ghfgfg"},
                "4" : {"operation": "add","value" : "4ghfgfg"}}

i have no clue how to proceed. any help will be much appreciated.

XSLT for extracting values of unique tags Below is the xsl which i have written. Need to club both your part and mine now.

    <xsl:for-each select="/pw:tpso/pw:serviceActions/pw:serviceAction">
    <xsl:choose>
     <xsl:when test="pw:parameters/pw:parameter/pw:name[string()='action']/../pw:value = 'add'">
      "<xsl:value-of select="pw:name"/>" : {"operation": "add","value" : "<xsl:value-of select="pw:parameters/pw:parameter/pw:name[string()='new']/../pw:value"/>"}
     </xsl:when>
     <xsl:when test="pw:parameters/pw:parameter/pw:name[string()='action']/../pw:value = 'del'">
      "<xsl:value-of select="pw:name"/>" : {"operation": "del","value" : "         <xsl:value-of select="pw:parameters/pw:parameter/pw:name[string()='old']/../pw:value"/>"}
     </xsl:when>
     <xsl:when test="pw:parameters/pw:parameter/pw:name[string()='action']/../pw:value = 'def'">
      "<xsl:value-of select="pw:name"/>" : {"operation": "def","value" : "<xsl:value-of select="pw:parameters/pw:parameter/pw:name[string()='new']/../pw:value"/>"}
     </xsl:when>
     <xsl:when test="pw:parameters/pw:parameter/pw:name[string()='action']/../pw:value = 'chg'">
      "<xsl:value-of select="pw:name"/>" : {"operation": "chg","newvalue" : "<xsl:value-of select="pw:parameters/pw:parameter/pw:name[string()='new']/../pw:value"/>", "oldvalue" : "<xsl:value-of select="pw:parameters/pw:parameter/pw:name[string()='old']/../pw:value"/>" }
     </xsl:when>

"" : {"operation": "def" ,"value" : ""}

    </xsl:choose>
</xsl:for-each>

Output needs to be like below "billing_model":{"operation":"del","value":"2"} "block_data_transfer":{"operation":"def","value":"NONE"} "bsg":{"operation":"del","value":""}

INput true 000027041866009@ALL CHANGE tpso for Element ALL Action CHANGE 4 2013-10-07T11:22:21.000+00:00 8 260060059948580 48727554404 MSISDN 48727554404 usage_state action add old new 0ghfgfg usage_state action add old new 1ghfgfg usage_state action add old new 2ghfgfg usage_state action add old new 3ghfgfg usage_state action add old new 4ghfgfg block_data_transfer action def old NONE new NONE bsg action del old new billing_model action del old new 2

هل كانت مفيدة؟

المحلول

This is an example of a grouping problem. If you are using XSLT 1.0, then you need to read up on Muenchian Grouping which is generally the most efficient way of handling such problems.

I am assuming you are grouping serviceAction elements by their name, so you start off by defining a key to look up serviceAction elements by name

 <xsl:key name="service" match="t:serviceAction" use="t:name" />

(Note, the t: prefix here is because in your original XML, all the elements are in the namespace="packetware:teleprovision", and so you will need to declare this in your XSLT too. I am using the prefix t for the declaration in this case).

Then, to get the distinct name elements, which form the basis of your group, the expression is as follows:

<xsl:apply-templates select="t:serviceActions/t:serviceAction
                             [generate-id() = generate-id(key('service', t:name)[1])]" />

This looks at all serviceAction elements, and finds the first one that occurs in the key for the value of its current name.

Then, to get the elements in each group, you can just iterate over the key, like so:

<xsl:for-each select="key('service', t:name)">

Try this XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:t="packetware:teleprovision">
    <xsl:output method="text"/>
    <xsl:key name="service" match="t:serviceAction" use="t:name" />

    <xsl:variable name="quote">"</xsl:variable>

    <xsl:template match="/*">
        <xsl:apply-templates select="t:serviceActions/t:serviceAction[generate-id() = generate-id(key('service', t:name)[1])]" />
    </xsl:template>

    <xsl:template match="t:serviceAction">
        "<xsl:value-of select="t:name" />": <xsl:text>{</xsl:text>
        <xsl:for-each select="key('service', t:name)">
            <xsl:if test="position() > 1">,</xsl:if>
            "<xsl:number />" : {
                "operation": "<xsl:value-of select="t:parameters/t:parameter[t:name='action']/t:value" />",
                "value" : "<xsl:value-of select="t:parameters/t:parameter[t:name='new']/t:value" />"
            <xsl:text>}</xsl:text>
        </xsl:for-each>
        }
    </xsl:template>
</xsl:stylesheet>

This outputs the following

    "usage_state": {
        "1" : {
            "operation": "add",
            "value" : "0ghfgfg"
        },
        "2" : {
            "operation": "add",
            "value" : "1ghfgfg"
        },
        "3" : {
            "operation": "add",
            "value" : "2ghfgfg"
        },
        "4" : {
            "operation": "add",
            "value" : "3ghfgfg"
        },
        "5" : {
            "operation": "add",
            "value" : "4ghfgfg"
        }
    }

Note, in XSLT 2.0, you can use xsl:for-each-group instead of the Muenchian grouping method, to simplify things.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top