Skip to Content

XML to ABAP using XSLT

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

Add comment
10|10000 characters needed characters exceeded

  • Get RSS Feed

4 Answers

  • Best Answer
    Nov 02, 2017 at 01:19 PM

    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>
    
    Add comment
    10|10000 characters needed characters exceeded

  • Oct 30, 2017 at 03:46 PM

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

    Add comment
    10|10000 characters needed characters exceeded

  • Nov 02, 2017 at 09:55 AM

    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 !

    Add comment
    10|10000 characters needed characters exceeded

  • Nov 03, 2017 at 08:13 AM

    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

    Add comment
    10|10000 characters needed characters exceeded