Skip to Content
0

XML to ABAP using XSLT

Oct 30, 2017 at 10:09 AM

147

avatar image

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

10 |10000 characters needed characters left characters exceeded
* Please Login or Register to Answer, Follow or Comment.

4 Answers

Best Answer
Sandra Rossi Nov 02, 2017 at 01:19 PM
0

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>
Share
10 |10000 characters needed characters left characters exceeded
Sandra Rossi Oct 30, 2017 at 03:46 PM
0

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).

Share
10 |10000 characters needed characters left characters exceeded
Henrik Mortensen Nov 02, 2017 at 09:55 AM
0

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 !

Share
10 |10000 characters needed characters left characters exceeded
Henrik Mortensen Nov 03, 2017 at 08:13 AM
0

Hi Sara,

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

Best Regards Henrik

Share
10 |10000 characters needed characters left characters exceeded