SAP MII : XSL zur Eliminierung einzelner XML-Knoten

von Tobias Vitzthum
SAP MII XSL Elimination of individual XML nodess

XSLT (Extensible Stylesheet Language Transformations) ist eine weitverbreitete Sprache zum Umwandeln von XML-Dokumenten. Sie ist wie XPath (XML Path Language; eine XML-Abfragesprache zum Navigieren innerhalb eines XML-Dokuments) und XSL-FO (Extensible Stylesheet Language Formatting Objects) Bestandteil von XSL (Extensible Stylesheet Language).

Mithilfe von XSLT kann ein XML-Quelldokument derartig verändert werden, dass im resultierenden Zieldokument die ursprünglichen Elemente sortiert oder neu angeordnet werden. Außerdem können einzelne Elemente und Attribute hinzugefügt oder gelöscht werden.

Das Grundprinzip von XSL ist es, mit XPath Teile eines Quelldokuments zu selektieren, die mit einer Vorlage („Template“) übereinstimmen und den passenden Teil in eine Ergebnisstruktur zu überführen.

In diesem Artikel werden wir eine XSL-Transformation benutzen, um einen Teil eines XML-Dokuments zu extrahieren bzw. um alle Elemente bis auf einige wenige zu kopieren.

Ursprungsdokument (Ergebnis einer SAP MII Tag-Query)

<?xml version="1.0" encoding="UTF-8"?>
<Rowsets>
    <Rowset>
        <Columns>
            <Column Description="DateTime" MaxRange="1" MinRange="0" Name="DateTime" SQLDataType="93" SourceColumn="DateTime"/>
            <Column Description="L1Speed" MaxRange="100" MinRange="0" Name="L1Speed" SQLDataType="8" SourceColumn="L1Speed"/>
            <Column Description="L2Speed" MaxRange="100" MinRange="0" Name="L2Speed" SQLDataType="8" SourceColumn="L2Speed"/>
            <Column Description="L3Speed" MaxRange="100" MinRange="0" Name="L3Speed" SQLDataType="8" SourceColumn="L3Speed"/>
            <Column Description="L4Speed" MaxRange="100" MinRange="0" Name="L4Speed" SQLDataType="8" SourceColumn="L4Speed"/>
        </Columns>
        <Row>
            <DateTime>2018-11-19T12:00:00</DateTime>
            <L1Speed>95.180979966365</L1Speed>
            <L2Speed>92.140226606556</L2Speed>
            <L3Speed>93.519108843627</L3Speed>
            <L4Speed>84.131727645383</L4Speed>
        </Row>
        <Row>
            <DateTime>2018-11-19T12:00:10</DateTime>
            <L1Speed>87.873907768722</L1Speed>
            <L2Speed>95.172678667383</L2Speed>
            <L3Speed>91.511432479393</L3Speed>
            <L4Speed>84.390037042337</L4Speed>
        </Row>
        <Row>
            <DateTime>2018-11-19T12:00:20</DateTime>
            <L1Speed>91.586207194496</L1Speed>
            <L2Speed>95.793222449562</L2Speed>
            <L3Speed>94.507301113587</L3Speed>
            <L4Speed>84.842097858627</L4Speed>
        </Row>
    </Rowset>
</Rowsets>
In der Zielstruktur wollen wir die Spaltenbeschreibungen („Columns“ und deren Kindelemente) sowie alle „L2Speed“- und „L3Speed“-Knoten entfernen. Darüber hinaus werden wir die Knoten „L1Speed“ in „L1“ und „L4Speed“ in „L4“ umbenennen.

Gewünschte Zielstruktur

<?xml version="1.0" encoding="UTF-8"?>
<Rowsets>
    <Rowset>
        <Row>
            <DateTime>2018-11-19T12:00:00</DateTime>
            <L1>95.180979966365</L1>
            <L4>84.131727645383</L4>
        </Row>
        <Row>
            <DateTime>2018-11-19T12:00:10</DateTime>
            <L1>87.873907768722</L1>
            <L4>84.390037042337</L4>
        </Row>
        <Row>
            <DateTime>2018-11-19T12:00:20</DateTime>
            <L1>91.586207194496</L1>
            <L4>84.842097858627</L4>
        </Row>
    </Rowset>
</Rowsets>

Mögliche Transformation via XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="utf-8" indent="yes"/>
    
    <!-- Identity template: copy all text nodes, elements and attributes -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <!-- When matching node "L1Speed", copy node as "L1" -->
    <xsl:template match="L1Speed">
        <xsl:element name="L1">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
    
    <!-- When matching node "L4Speed", copy node as "L4" -->
    <xsl:template match="L4Speed">
        <xsl:element name="L4">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
    
    <!-- When matching nodes "Columns", "L2Speed", "L3Speed" do nothing -->
    <xsl:template match="Columns|L2Speed|L3Speed"/>
    
</xsl:stylesheet>

Das erste definierte Template adressiert alle Knoten, Elemente und Attribute (@*|node()) in unserem Quelldokument, erstellt eine Kopie des jeweiligen Knotens bzw. Attributs (xsl:copy) und wendet weitere Templates auf das aktuelle Element und dessen Unterelemente an.

Im zweiten Template reagieren wir auf alle Knoten mit dem Namen „L1Speed“ und übernehmen dessen Wert in ein neues XML-Element „L1“. Analog dazu verarbeitet das dritte Template die Knoten „L4Speed“.

Das letzte Template wird ausgeführt, wenn der Name des Knotens „Columns“, „L2Speed“ oder „L3Speed“ ist, da es aber keine weiteren Anweisungen in diesem Template gibt, werden diese Knoten nicht in das Ergebnisdokument übernommen.