XML-Basics / XML-Kommentare

XML-Kommentare

XML-Kommentare

➪ In XML, XSLT, XML-Schema und anderen Standards sind ergänzende Kommentare hilfreich, um die Wartung komplexer Anwendungen zu erleichtern. Neben Standard-Kommentaren stehen auch CDATA-Kommentare bereit.

Ergänzende Kommentare können weitere Hilfestellung geben. Ein Standard-XML-Kommentar beginnt mit <!-- und endet mit -->.


<root>
   <!-- this is a comment, you are free to write down your CV -->
</root>

XML-Kommentare in XSL erzeugen

In XSL ist es angebracht, zum besseren Verständnis der Programmlogik lokale Kommentare einzubauen, die nicht im Ergebnisdokument erscheinen. Sinnvolle Kommentare im Quelltext können die Wartung der Programme sehr erleichtern, daher sind sie unbedingt zu empfehlen.


<erg>
  <!-- dieser Kommentar gilt nur lokal in XSL, 
       wird nicht im Ergebnisdokument erscheinen -->
</erg>

Die Ausgabe im Ergebnisdokument lautet wie beabsichtigt ohne Kommentar:


<erg/>

Um im Ergebnisdokument einen Kommentar sichtbar zu machen, können Sie mit <xsl:comment> arbeiten.


<erg>
  <xsl:comment>Dieser Kommentar wird im Ergebnis erscheinen</xsl:comment>
</erg>

Die Ausgabe im Ergebnisdokument lautet:


<erg>
  <!--Dieser Kommentar wird im Ergebnis erscheinen-->
</erg>

XML-Kommentare in XSL auswerten

Umgekehrt ist es auch möglich, mit XSLT die Kommentare in den Input-Dokumenten auszuwerten. Betrachten Sie folgendes XML-Input-Dokument, das (abgesehen von einem "root"-Node) ausschließlich XML-Kommentare aufweist.


<root>
<!--Kommentar 1-->
<!--Kommentar 2-->
<!--Kommentar 3-->
<!--Kommentar 4-->
</root>

Nun soll versucht werden, diese Kommentare in XSLT auszuwerten. Das funktioniert recht einfach:


<xsl:stylesheet version="1.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" 
              version="1.0" 
              encoding="UTF-8" 
              indent="yes"/>
  <xsl:template match="/">
    <Kommentare>
      <xsl:for-each select="/root/comment()">
        <info>
          <xsl:value-of select="."/>
        </info>
      </xsl:for-each>
    </Kommentare>
  </xsl:template>
</xsl:stylesheet>

Das Ergebnis ist wenig überraschend:


<?xml version="1.0" encoding="UTF-8"?>
<Kommentare>
	<info>Kommentar 1</info>
	<info>Kommentar 2</info>
	<info>Kommentar 3</info>
	<info>Kommentar 4</info>
</Kommentare>

Das obige XSL-Stylesheet konzentriert sich jedoch nur auf jene Kommentare, die unmittelbar unterhalb des "root"-Elements stehen. In der Regel sieht die Datenstruktur jedoch etwas komplexer aus:


<root>
 <!--Kommentar 1-->
 <Ebenea>
  <ka>
   <!--Kommentar 2-->
  </ka>
  <Ebeneb>
   <kb>
    <!--Kommentar 3-->
   </kb>
   <Ebenec>
    <kc>
     <!--Kommentar 4-->
    </kc>
   </Ebenec>
  </Ebeneb>
 </Ebenea>
</root>

Möchten Sie nun nicht nur sämtliche Kommentare auf unterschiedlichen Ebenen auslesen, sondern auch den XPath zu dieser Ebene wissen, so können Sie sich hiermit behelfen:


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
 <xsl:template match="/">
  <Kommentare>
   <xsl:for-each select="/*/descendant-or-self::*/comment()">
    <info>
     <xsl:attribute name="xpath">
      <xsl:for-each select="ancestor-or-self::*">
       <xsl:text>/</xsl:text>
       <xsl:value-of select="name()"/>
      </xsl:for-each>
     </xsl:attribute>
     <xsl:value-of select="."/>
    </info>
   </xsl:for-each>
  </Kommentare>
 </xsl:template> 
</xsl:stylesheet>

Das Ergebnis hilft Ihnen weiter:


<Kommentare>
 <info 
    xpath="/root">Kommentar 1</info>
 <info 
    xpath="/root/Ebenea/ka">Kommentar 2</info>
 <info 
    xpath="/root/Ebenea/Ebeneb/kb">Kommentar 3</info>
 <info 
    xpath="/root/Ebenea/Ebeneb/Ebenec/kc">Kommentar 4</info>
</Kommentare>

CDATA in Scripting-Dateien

Neben Standard-Kommentaren gibt es noch CDATA-Kommentare. CDATA-Kommentare beginnen mit <![CDATA[ und enden mit ]]>.

Im Unterschied zu den Parsed Character Data (PCDATA), die durch einen Parser verarbeitet werden, beinhalten CDATA-Kommentare Daten, die nicht geparst werden. CDATA-Kommentare erlauben beispielsweise, zusätzliche XML-Elemente einzufügen, die im XML-Schema nicht definiert sind. Durch CDATA wird es möglich, diese nicht-validen Inhhalte vor etwaiger Validierung gegen DTD oder XML-Schema zu schützen.

Einen Einsatzbereich für CDATA-Kommentare finden Sie beispielsweise in Windows-Scripting-Dateien, die im Kern XML-Dokumente darstellen, deren Scriptanteile jedoch über den Windows Script Host ausgeführt werden können.


<?xml version="1.0" encoding="ISO-8859-1"?>
<job id="T1">
    <comment>
        <c1>File: dosomething.wsf</c1>
        <c1>Author: Wilfried Grupe</c1>
        <c1>Datum: 01.01.2018</c1>
        <c1>Description: writes Hello</c1>
    </comment>
    <script language="VBScript">
<![CDATA[
sub dosomething
    wscript.echo "Hallo"
end sub
]]>
    </script>
    <script language="JScript">
<![CDATA[
try { 
    // calling vbscript from JScript:
    dosomething(); 
}
catch(e) { 
    // Exceptionhandling in case something is going wrong
    WScript.echo(e.description); 
}
]]>
    </script>
</job>

Einen vergleichbaren Einsatzzweck findet der CDATA-Kommentar in ANT, wo mittels JavaScript mehrere ANT-Echoaufrufe generiert werden, die im Ergebnis das unten stehende Bild ergeben.


  <target name="jstest">
    <script language="javascript">
    <![CDATA[          
      for(var z=0; z<15;z++){
        var str="";        
        for(var s=0; s<48; s++) {
          if(    z===s || s+z===14 
            || s===17 || s===31  || s===33 
            || (z==14 && s > 33) 
            || (z < 8) &&(s===17+z || z+s===31 )){
            str = str + "#";
          }
          else str = str + " ";
        }      
        var ve = MYANTPROJECT.createTask("echo");
        ve.setMessage(str);
        ve.perform();
      }        
    ]]>
    </script>
  </target>

pic/jstest.png

In xsl:output kann definiert werden, welche Elemente in CDATA-Section dargestellt werden sollen:


<xsl:output method="xml" indent="yes" 
     cdata-section-elements="erg wert" />

CDATA-Sections und XML-Schema-Validierung

Häufig validieren Datenempfänger ihre XML-Dokumente "sehr scharf" gegen ein XML-Schema. Mitunter sind in den XML-Dokumenten jedoch CDATA-Sections enthalten, die Inhalte "maskieren", einer XSD-Validierung entziehen und so eine geforderte, eindeutige Strukturdefinition aushebeln.

Es bleibt dem Developer überlassen, bei eventuellen strukturellen Änderungen in den CDATA-Sections die Verarbeitungslogik (XSL, XQuery) anzupassen. Es kann aber vorkommen, dass diese Anpassung unterbleibt oder verzögert vorgenommen wird. Dann droht hier ein Informationsverlust, der sehr teuer werden kann.

Hierzu möchte ich ein einfaches Beispiel geben. Das folgende XML-Schema definiert ein Root-Element Person mit drei xs:string-Childnodes Vorname, Nachname und info.


<xs:schema 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  attributeFormDefault="unqualified"
  elementFormDefault="unqualified" version="1.0" >
  <xs:element name="Person" type="PersonTYP"/>
  <xs:complexType name="PersonTYP">
    <xs:sequence>
      <xs:element ref="Vorname" />        
      <xs:element ref="Nachname" />
      <xs:element ref="info" />
    </xs:sequence>
  </xs:complexType>
  <xs:element name="Vorname" type="xs:string" />
  <xs:element name="Nachname" type="xs:string" />
  <xs:element name="info" type="xs:string" />
</xs:schema>

Das folgende XML-Dokument übernimmt Vorname und Nachname, weist der info aber einen zusätzlichen Childnode Hobby zu, das im XML-Schema nicht vorgesehen ist; ihre Existenz im XML-Dokument sollte daher zu einem Validierungsfehler führen.


<Person 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="Person.xsd">
  <Vorname>Vorname</Vorname>  
  <Nachname>Nachname</Nachname>
  <info><Hobby>XML</Hobby></info>
</Person>

Der Validierungsfehler lässt auch nicht auf sich warten:


Element 'info' ist Simple Type und 
darf daher keine Elementinformationselemente 
[untergeordnete Elemente] haben. 
Person.xml is not a valid XML document

Dagegen geht die CDATA-"Maskierung" glatt durch:


<Person 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="Person.xsd">
  <Vorname>Vorname</Vorname>  
  <Nachname>Nachname</Nachname>
  <info><![CDATA[ <Hobby>XML</Hobby>]]> </info>
</Person>

Alternativ denkbar wäre, die Daten ohne CDATA-Section als Text mit Entitäten einzubinden; auch hier würde eine Validierung gegen das vorher beschriebene XML-Schema problemlos durchlaufen:


<Person 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="Person.xsd">
  <Vorname>Vorname</Vorname>  
  <Nachname>Nachname</Nachname>
  <info>&lt;Hobby&gt;XML&lt;/Hobby&gt;</info>
</Person>

In beiden Fällen stellen sich aus meiner Sicht einige Fragen:

parse-xml-fragment

Obwohl CDATA-Kommentare nicht geparst werden und Inhalte betreffen können, die einer XML-Schema-Validierung widersprechen, ist es doch möglich, dass diese Inhalte von Belang sind. Die XPath-Funktion parse-xml-fragment erlaubt deren Auswertung.


 <xsl:variable name="vfeld">
  <![CDATA[
  <root>
    <i>Straße2</i>
    <i>Strasse1</i>
    <i>Weg</i>
    <i>Straße1</i>
    <i>Strasse2</i>
    <i>Pfad</i>
    </root>
   ]]>
 </xsl:variable>

Variablen wie vfeld können Sie mit der XPath-Funktion parse-xml-fragment in ein XML-Dokument überführen und dieses auswerten.


<ergebnis>
  <xsl:for-each 
       select="parse-xml-fragment($vfeld)/root/i">
    <wert>
     <xsl:value-of select="."/>
    </wert>
  </xsl:for-each>   
</ergebnis>

Daß dies gelungen ist, sehen Sie hier:


<ergebnis>
   <wert>Straße2</wert>
   <wert>Strasse1</wert>
   <wert>Weg</wert>
   <wert>Straße1</wert>
   <wert>Strasse2</wert>
   <wert>Pfad</wert>
</ergebnis>

wg / 13. April 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/Kommentare.html