Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

XML to ABAP using XSLT

henrik_mortensen
Explorer
0 Likes
3,518

Hi, I'm a bit stuck with an XSLT translation issue. I've used the same setup as in the tutorial from Jan Krohn, https://www.heidoc.net/joomla/technology-science/sap-and-xslt/5-tutorial

I've got most it to work, however I'm very uncertain how to handle 2nd line i the XML file process in my XSLT transformation.

<?xml version="1.0" ?>
<alarm xmlns="http://xxx.xxx.xxx/types">
  <quality bad="0" realtime="1"/>
  <ts>2017-10-26T23:58:24.056</ts>
  <pbs native="XXXX-L001_PF-PS-MVS-52DF1_Q1100" n="" l2="100" l1="Q1" q="52DF1-" r="MVS" s="PS-" t="PF" a4="" a3="01" a2="L0" a1="XXXXX-XXX</pbs>
  <sign prog="01" code="A3"/>
  <sender>test</sender>
  <state>3</state>
  <property autogen="0" internal="0" prio="3"/>
  <initTs>2017-10-26T23:58:24.056</initTs>
</alarm>

If I remove the

xmlns="http://xxx.xxx.xxx/types

it works fine, but If I let it stay I don't get any data durring the XSLT transformation

My XSLT look like this:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="/">
    <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
      <asx:values>
        <IALARMS>
          <xsl:apply-templates select="//alarm"/>
        </IALARMS>
      </asx:values>
    </asx:abap>
  </xsl:template>

  <xsl:template match="alarm">
      <QUALITY>
        <xsl:value-of select="quality"/>
      </QUALITY>
      <TS>
        <xsl:value-of select="ts"/>
      </TS>
      <PBS>
        <xsl:value-of select="pbs"/>
      </PBS>
      <SIGN>
        <xsl:value-of select="sign"/>
      </SIGN>
      <SENDER>
        <xsl:value-of select="sender"/>
      </SENDER>
      <STATE>
        <xsl:value-of select="state"/>
      </STATE>
      <PROPERTY>
        <xsl:value-of select="property"/>
      </PROPERTY>
      <INITTS>
        <xsl:value-of select="initts"/>
      </INITTS>
  </xsl:template>
</xsl:transform>

What do I need to change in XSLT for getting the XML transformed correctly ?.

Another issue, how to I manage to read the attributes in some of the nodes ? I've read several articles, and some are telling I can do "@attrib name" However I never get it to work.

If I put this question into the wrong group, I'm sry for that 🙂

Brgds

Henrik Mortensen

1 ACCEPTED SOLUTION
Read only

Sandra_Rossi
Active Contributor
0 Likes
2,309

Thank you for having posted the latest code (especially the TYPES).

I could make it work.

Here is the ABAP code I used / I added the namespace for all elements / To have 2 alarms, you must embed them into one root element as per XML standards ("alarms" here) :

DATA string TYPE string.
CONCATENATE
'<?xml version="1.0" encoding="UTF-8"?>               '
'<alarms xmlns="http://xxx.xxx.xxx/types">             '
'<alarm>             '
'  <quality realtime="1" bad="0"/>                    '
'  <ts>2014-11-24T15:17:47.003</ts>                   '
'  <pbs native="native text"></pbs>                   '
'  <sign code="A5" prog="05"/>                        '
'  <sender>MySender</sender>                          '
'  <state>2</state>                                   '
'  <property prio="5" internal="0" autogen="1"/>      '
'  <initTs>2014-11-24T15:16:42.003</initTs>           '
'  <normTs>2014-11-24T15:17:47.003</normTs>           '
'  <lob>                                              '
'    <sign>                                           '
'      <name lang="0" value="Some text for line 1)"/> '
'      <name lang="1" value="Some text for line 2"/>  '
'    </sign>                                          '
'  </lob>                                             '
'</alarm>                                             '
'<alarm>             '
'  <quality realtime="999" bad="0"/>                  '
'</alarm>                                             '
'</alarms>                                            '
INTO string.

CALL TRANSFORMATION zzsro SOURCE XML string RESULT alarms = gt_alarms.
BREAK-POINT.

Here is the corrected XSLT transformation:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:zz="http://xxx.xxx.xxx/types" version="1.0">
  <xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="/">
    <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
      <asx:values>
        <ALARMS>
          <xsl:apply-templates select="/zz:alarms/zz:alarm"/>
        </ALARMS>
      </asx:values>
    </asx:abap>
  </xsl:template>
  <xsl:template match="/zz:alarms/zz:alarm">
    <item>
      <QUALITY_BAD>
        <xsl:value-of select="zz:quality/@bad"/>
      </QUALITY_BAD>
      <QUALITY_REALTIME>
        <xsl:value-of select="zz:quality/@realtime"/>
      </QUALITY_REALTIME>
      <TS>
        <xsl:value-of select="zz:ts"/>
      </TS>
      <PBS>
        <xsl:value-of select="zz:pbs/@native"/>
      </PBS>
      <SIGN_PROG>
        <xsl:value-of select="zz:sign/@prog"/>
      </SIGN_PROG>
      <SIGN_CODE>
        <xsl:value-of select="zz:sign/@code"/>
      </SIGN_CODE>
      <SENDER>
        <xsl:value-of select="zz:sender"/>
      </SENDER>
      <STATE>
        <xsl:value-of select="zz:state"/>
      </STATE>
      <PROP_AUTOGEN>
        <xsl:value-of select="zz:property/@autogen"/>
      </PROP_AUTOGEN>
      <PROP_INTERNAL>
        <xsl:value-of select="zz:property/@internal"/>
      </PROP_INTERNAL>
      <PROP_PRIO>
        <xsl:value-of select="zz:property/@prio"/>
      </PROP_PRIO>
      <INITTS>
        <xsl:value-of select="zz:initTs"/>
      </INITTS>
      <LOB>
        <xsl:for-each select="zz:lob">
          <item>
            <SIGN>
              <xsl:for-each select="zz:sign">
                <item>
                  <NAME>
                    <xsl:for-each select="zz:name">
                      <item>
                        <LANG>
                          <xsl:value-of select="@lang"/>
                        </LANG>
                        <VALUE>
                          <xsl:value-of select="@value"/>
                        </VALUE>
                      </item>
                    </xsl:for-each>
                  </NAME>
                </item>
              </xsl:for-each>
            </SIGN>
          </item>
        </xsl:for-each>
      </LOB>
    </item>
  </xsl:template>
</xsl:transform>
4 REPLIES 4
Read only

Sandra_Rossi
Active Contributor
0 Likes
2,309

I'm not sure to understand the question(s) correctly.

If you want the XML to contain 2 or more "alarm", then the XML must have all these alarms inside one root element (<alarms> for instance) because an XML may have only one root element. In the XSLT you need to use a loop with <xsl:for-each select="alarm">...

If your XML has a default namespace xmlns="http://...", then it means that all elements have names of this namespace. In the XSLT, you must define a namespace prefix for this namespace (xmlns:prefix="http://..." with any value for prefix), and the element names must be prefixed with this prefix (select="//prefix:alarm")

Indeed, use "@attrib name" for working with attributes (for instance <xsl:value-of select="@hash"/> which gets the attribute hash of the current node).

Read only

henrik_mortensen
Explorer
0 Likes
2,309

Hi Sandra,

In the XML document, I have the line:

<alarm xmlns="http://xxx.xxx.xxx/types">

It seems the XSLT in SAP is not happy about the

xmlns="http://xxx.xxx.xxx/types

If I remove this from the XML document, it works fine and if not I don't get anything back from SAP

Another issue I ran into was using nested tables.

In this XML document I have the node LOB, which can have 3 sub nodes called <sign> <pbs> <detail> and each of these have the node called <name> which have 2 attributes @lang and @value.

I've tried to setup the structure as per my understanding of the xml structure, however I'm not getting any results for @lang @value back in SAP. I do get data bac from rest of the <ALARM> node, just not <LOB>.

<?xml version="1.0" encoding="UTF-8"?>
<alarm>
  <quality realtime="1" bad="0"/>
  <ts>2014-11-24T15:17:47.003</ts>
  <pbs native="native text</pbs>
  <sign code="A5" prog="05"/>
  <sender>MySender</sender>
  <state>2</state>
  <property prio="5" internal="0" autogen="1"/>
  <initTs>2014-11-24T15:16:42.003</initTs>
  <normTs>2014-11-24T15:17:47.003</normTs>
  <lob>
    <sign>
      <name lang="0" value="Some text for line 1)"/>
      <name lang="1" value="Some text for line 2"/>
    </sign>
  </lob>
</alarm> 
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="/">

    <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
      <asx:values>
        <IALARMS>
          <xsl:apply-templates select="/alarm"/>
        </IALARMS>
      </asx:values>
    </asx:abap>
  </xsl:template>

  <xsl:template match="alarm">
    <item>
      <QUALITY_BAD>
        <xsl:value-of select="quality/@bad"/>
      </QUALITY_BAD>
      <QUALITY_REALTIME>
        <xsl:value-of select="quality/@realtime"/>
      </QUALITY_REALTIME>
      <TS>
        <xsl:value-of select="ts"/>
      </TS>
      <PBS>
        <xsl:value-of select="pbs/@native"/>
      </PBS>

      <SIGN_PROG>
        <xsl:value-of select="sign/@prog"/>
      </SIGN_PROG>

      <SIGN_CODE>
        <xsl:value-of select="sign/@code"/>
      </SIGN_CODE>

      <SENDER>
        <xsl:value-of select="sender"/>
      </SENDER>

      <STATE>
        <xsl:value-of select="state"/>
      </STATE>

      <PROP_AUTOGEN>
        <xsl:value-of select="property/@autogen"/>
      </PROP_AUTOGEN>

      <PROP_INTERNAL>
        <xsl:value-of select="property/@internal"/>
      </PROP_INTERNAL>

      <PROP_PRIO>
        <xsl:value-of select="property/@prio"/>
      </PROP_PRIO>

      <INITTS>
        <xsl:value-of select="initTs"/>
      </INITTS>

      <LOB>
        <xsl:for-each select="lob">
          <ITEM1>

            <xsl:for-each select="sign">
              <ITEM2>

                <xsl:for-each select="name">
                  <ITEM3>
                    <LANG>
                      <xsl:value-of select="@lang"/>
                    </LANG>
                    <VALUE>
                      <xsl:value-of select="@value"/>
                    </VALUE>
                  </ITEM3>
                </xsl:for-each>
              </ITEM2>
            </xsl:for-each>
          </ITEM1>
        </xsl:for-each>

      </LOB>
    </item>
  
</xsl:template>
</xsl:transform>


"ALARMS !!!!!

TYPES: BEGIN OF t_values,
         lang  TYPE string,
         value TYPE string,
       END OF t_values,

       tt_values TYPE t_values OCCURS 0.

TYPES: BEGIN OF t_name,
         name TYPE tt_values,
       END OF t_name,

       tt_name TYPE t_name OCCURS 0.

TYPES: BEGIN OF t_lob,
         sign TYPE tt_name,
         detail type tt_name,
         pbs type tt_name, 
       END OF t_lob,

       tt_lob TYPE t_lob OCCURS 0.

TYPES: BEGIN OF t_alarm,
         quality_bad      TYPE string, "bad= realtime= ??
         quality_realtime TYPE string,
         ts               TYPE string,  "TimeStamp
         pbs              TYPE string, "Native= n= i2= i1= q= r= s= t= a4= a3= a2= a1=
         sign_prog        TYPE string, "prog = code =
         sign_code        TYPE string,
         sender           TYPE string,
         state            TYPE string,
         prop_autogen     TYPE string, "autogen= internal= pric=
         prop_internal    TYPE string,
         prop_prio        TYPE string,
         initts           TYPE string,
         lob              TYPE tt_lob, "???
       END OF t_alarm.

DATA: gt_alarms TYPE STANDARD TABLE OF t_alarm,
      gs_alarm  TYPE t_alarm.

I tried find any examples with using Nested tables in XSLT for SAP, however I'm stuck so any help are highly apriciated !

Read only

Sandra_Rossi
Active Contributor
0 Likes
2,310

Thank you for having posted the latest code (especially the TYPES).

I could make it work.

Here is the ABAP code I used / I added the namespace for all elements / To have 2 alarms, you must embed them into one root element as per XML standards ("alarms" here) :

DATA string TYPE string.
CONCATENATE
'<?xml version="1.0" encoding="UTF-8"?>               '
'<alarms xmlns="http://xxx.xxx.xxx/types">             '
'<alarm>             '
'  <quality realtime="1" bad="0"/>                    '
'  <ts>2014-11-24T15:17:47.003</ts>                   '
'  <pbs native="native text"></pbs>                   '
'  <sign code="A5" prog="05"/>                        '
'  <sender>MySender</sender>                          '
'  <state>2</state>                                   '
'  <property prio="5" internal="0" autogen="1"/>      '
'  <initTs>2014-11-24T15:16:42.003</initTs>           '
'  <normTs>2014-11-24T15:17:47.003</normTs>           '
'  <lob>                                              '
'    <sign>                                           '
'      <name lang="0" value="Some text for line 1)"/> '
'      <name lang="1" value="Some text for line 2"/>  '
'    </sign>                                          '
'  </lob>                                             '
'</alarm>                                             '
'<alarm>             '
'  <quality realtime="999" bad="0"/>                  '
'</alarm>                                             '
'</alarms>                                            '
INTO string.

CALL TRANSFORMATION zzsro SOURCE XML string RESULT alarms = gt_alarms.
BREAK-POINT.

Here is the corrected XSLT transformation:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:zz="http://xxx.xxx.xxx/types" version="1.0">
  <xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="/">
    <asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
      <asx:values>
        <ALARMS>
          <xsl:apply-templates select="/zz:alarms/zz:alarm"/>
        </ALARMS>
      </asx:values>
    </asx:abap>
  </xsl:template>
  <xsl:template match="/zz:alarms/zz:alarm">
    <item>
      <QUALITY_BAD>
        <xsl:value-of select="zz:quality/@bad"/>
      </QUALITY_BAD>
      <QUALITY_REALTIME>
        <xsl:value-of select="zz:quality/@realtime"/>
      </QUALITY_REALTIME>
      <TS>
        <xsl:value-of select="zz:ts"/>
      </TS>
      <PBS>
        <xsl:value-of select="zz:pbs/@native"/>
      </PBS>
      <SIGN_PROG>
        <xsl:value-of select="zz:sign/@prog"/>
      </SIGN_PROG>
      <SIGN_CODE>
        <xsl:value-of select="zz:sign/@code"/>
      </SIGN_CODE>
      <SENDER>
        <xsl:value-of select="zz:sender"/>
      </SENDER>
      <STATE>
        <xsl:value-of select="zz:state"/>
      </STATE>
      <PROP_AUTOGEN>
        <xsl:value-of select="zz:property/@autogen"/>
      </PROP_AUTOGEN>
      <PROP_INTERNAL>
        <xsl:value-of select="zz:property/@internal"/>
      </PROP_INTERNAL>
      <PROP_PRIO>
        <xsl:value-of select="zz:property/@prio"/>
      </PROP_PRIO>
      <INITTS>
        <xsl:value-of select="zz:initTs"/>
      </INITTS>
      <LOB>
        <xsl:for-each select="zz:lob">
          <item>
            <SIGN>
              <xsl:for-each select="zz:sign">
                <item>
                  <NAME>
                    <xsl:for-each select="zz:name">
                      <item>
                        <LANG>
                          <xsl:value-of select="@lang"/>
                        </LANG>
                        <VALUE>
                          <xsl:value-of select="@value"/>
                        </VALUE>
                      </item>
                    </xsl:for-each>
                  </NAME>
                </item>
              </xsl:for-each>
            </SIGN>
          </item>
        </xsl:for-each>
      </LOB>
    </item>
  </xsl:template>
</xsl:transform>
Read only

henrik_mortensen
Explorer
0 Likes
2,309

Hi Sara,

Ah I see, I missed the ABAP nodes <SIGN> and <NAME> !! Now everything are working as supposed 😄 thanks a bunch for your input. May you have pleasant weekend.

Best Regards Henrik