XML und XSLT

Alle Skripte sind Muster ohne jede Gewährleistung oder Funktionsgarantie. für Schäden bin ich nicht verantwortlich. Achten Sie auf Zeilenumbrüche bei der Übernahme.

Wohin Sie heute auch schauen begegnen Sie immer wieder dem Begriff XML. Ich habe auch lange Zeit die Bedeutung von XML unterschätzt und die Speicherung von Informationen in XML als Weiterentwicklung der früheren CSV-Dateien angesehen.

CSV, ein Vorgänger von XML ?

Habt man früher z.B.: seine Kontakte exportiert, so war eine Textdatei mit den Datenfeldern als Spalten und den Datensätzen als Zeilen ein universelles Format zum Austausch, z.B.

Name; Vorname; Strasse; PLZ; Ort
Carius; Frank; Hegselweg; 33415; Verl
Mantke; Ingrid; Hegselweg; 33415; Verl

Aber sehr schnell wird klar, dass hiermit nur eindimensionale Tabellen möglich sind, Wenn ich nun mehrere Wohnsitze habe, dann müsste dies durch mehrere Zeilen vorgegeben werden. Auch die Formate sind nicht definiert. Das eine Programm erwartet ein "Komma" (,) als Trennzeichen, andere wieder einen Tabulator (TAB) oder ein Semikolon (;). Auch die umlaute sind nicht einfach, wenn eine Software die Datei als ASCII, eine andere als ANSI oder sogar UNICODE speichert.

Aber lange Zeit war dieses Format im Gebrauch. Auch der Exchange 5.5 Administrator hat z.B. einen Export als CSV-Datei abgelegt.

Was ist XML ?

XML ist eine Beschreibung zur Speicherung von Informationen jeglicher Art in Dateien zum einfachen Austausch und der Weiterverarbeitung. XML wird ähnlich wie HTML mit Tags aufgebaut. Allerdings sind hier sehr strikte Regeln zu beachten. So muss jedes geöffnete Token auch wieder geschlossen werden. Die obige CSV-Datei könnten z.B. so aussehen:

Es muss in einer XML-Datei immer genau einen ROOT-Knoten geben. Der muss natürlich nicht <root> heißen. Zur Vereinfachung habe ich hier auf Definitionen zum Zeichensatz oder einem Stylesheet weg gelassen.

im XML-Format gespeicherte Daten müssen aber nicht zwingend als Datei vorliegen. Auch Tabellen in Datenbanken, die METABASE des IIS aber auch HTML-Anfragen an Exchange mittels WebDAV nutzen XML-Pakete. XML verbindet den universalen Ansatz zum Datenaustausch mit einer klaren Struktur und bietet damit eine sehr hohe Flexibilität und Interoperabilität.

Sie sehen aber schon am Format, dass z.B. das Zeichen "<" nicht einfach im Text verwendet werden kann, da es die Tags kennzeichnet. Solche Zeichen müssen also "Escaped" werden, z.B. mit "&lt;". Entsprechend muss auch das Ampersand-Zeichen selbst mit "&amp;" angelegt werden. Die meisten XML-Parser machen das aber alleine. Nur wer selbst per Textdatei eine XML-Ausgabe anfertigt, muss an sowas denken.

Zeichen Beschreibung Ersatzschreibweise

&

Ampersand

&amp;

>

Größer als

&gt;

<

Kleiner als

&lt;

'

Apostroph

&apos;

"

Quote

&quot;

Die meisten Schreibweisen kommen ihnen aus HTML schon sicher bekannt vor. Anhand der Ausnahmen sehen Sie schon, dass z.B. LDAP-Filter oder Pfadangaben als Dateninformation in XML-Dateien hier problematisch sein können.

XML mit XSL konvertieren

Nur was macht man nun mit der neuen Freiheit ? natürlich kann eine andere Software nun einfach diese Daten importieren und exportieren. Aber zusammen mit der Definition von XML wurden auch so genannte Stylesheets definiert. Diese beschreiben z.B.: eine umformatierung. Mit folgendem Stylesheet würde aus dem XML-File eine HTML-Tabelle.

Der XML-Parser liest die XML und die darin spezifizierte XSL-Datei ein und generiert daraus eine Ausgabe. Der Internet Explorer ist ein solcher Parser und beim Doppelklick auf die XML-Datei erhalten Sie folgende Ausgabe:

Das ist eine einfache Funktion, um aus dem reinen Datenformat XML eine entsprechende Ausgabe zu erstellen. Es gibt mittlerweile auch XSL-Stylesheets, die z.B. Word, Excel oder PDF-Dokumente erzeugen. Die Grenzen sind noch nicht abzusehen. Hier die Dateien zum Download:

xmlsample.xml Die XML-Datei mit den Adressdaten
xmlsample.xsl Ein Stylesheet zur Konvertierung nach HTML
Bitte beachten Sie, dass Sie die Erweiterung "TXT" erst entfernen.

Es gibt von Microsoft auch eine Kommandozeile zum Aufruf des XML-Parsers. damit können die auch aus einem Batch heraus eine XML-Datei mit einer angegebenen XSL-Datei in ein Zielformat konvertieren. Sollten Sie MSXSL.EXE auf ihren PC noch nicht haben, dann helfen ihnen folgende beiden Links weiter.

Download MSXSL  (nicht mehr aktuell)
http://www.Microsoft.com/downloads/details.aspx?FamilyID=2fb55371-c94e-4373-b0e9-db4816552e41&DisplayLang=en

Command Line Transformation Utility (msxsl.exe)
https://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=21714

Eventuell kommen Sie mit MSXLS 6 weiter.

Microsoft Core XML Services (MSXML) 6.0
https://www.microsoft.com/de-de/download/details.aspx?id=3988

Das ist aber nur eine DLL. Mit etwas PowerShell lässt sich da aber was machen

# transform XML with XSLT
param (
	[string]$xmlfile
	[string]$xsltfile
	[string]$outfile
)

write-host "Initialize Msxml2.DOMDocument.6.0"
$xmlobj = New-Object -ComObject Msxml2.DOMDocument.6.0 
$xmlobj.async = $false

write-host "Load XML-File $($xmlfile)"
$xmlobj.Load($xmlfile)

write-host "Initialize Msxml2.DOMDocument.6.0"
$xslt = New-Object -ComObject Msxml2.DOMDocument.6.0 

write-host "Load XSLT-File $($xsltfile)"
$xslt.async = $false
$xslt.Load($xsltfile)

Write-host "Starting transformation"
$transformed = $xmlfileobj.transformNode($xslt)

Write-host "Write output to $outfile"
$transformed | Set-content -path $outfile

Write-host "Cleanup Opbjects
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xmlfileobj)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xslt)

Write-Host "Done!"

Starten Sie nach der Analyse der Postfächer einfach MSXSL.EXE mit der erzeugten XML-Datei als Quelle, dem Stylesheet und der gewünschten Ausgabedatei:

msxsl.exe eingabe.xml konvert.xsl -o Ausgabedatei

Dies Flexibilität hat mich auch nach einiger Zeit dazu bewogen, dass viele Programme ihre Ausgaben nicht mehr alleine auf den Bildschirm, einfache Textdateien oder CSV-Dateien schreiben, sondern die Ausgabe der aufbereiteten Daten als XML viel flexibler ist. Mit dem passenden Stylesheet ist nahezu jede Weiterverarbeitung möglich. Das geht soweit, dass Sie die beiden Dateien einfach auf ihren IIS kopieren und beim Aufruf der XML-Datei diese vom Webserver konvertiert und an den Client ausgeliefert wird.

Natürlich sind XML-Dateien größer als ein proprietäres binäres Format. Es hindert Sie ja auch niemand daran, ihre Daten nicht als XML zu speichern, aber erst die Speicherung als XML erlaubt eine einfache weitere Verarbeitung und darauf kommt es in Zukunft ja auch an. XML ist das Bindeglied zwischen Prozessen, Diensten und auch Betriebssystemen.

XML und CSS

Auch wenn CSS eigentlich für die Formatierung von HTMLSeiten vorgesehen ist, kann man mit halbwegs aktuellen Browsern damit sogar XML-Dateien formatieren. Dazu ist im XML-File einfach das Stylesheet mit anzugeben

<?xml-stylesheet type="text/css" href="format.css" ?>

Allerdings werden damit nur "Formatinformationen" an die XMLElemente angefügt, die ein Browser entsprechend "netter" anzeigen kann. Wer hingegen die Daten einer XML-Datei in eine

XML als Programmierer

Wenn Sie nun von XML begeistert sind, dann stellen Sich natürlich die Frage, wie sie selbst in ihren Programmen XML lesen, schreiben und verarbeiten. Es gibt natürlich von Microsoft für Windows entsprechende Bibliotheken, so dass Sie nicht selbst mit Textdateien hantieren müssen. Entsprechende Beispiele finden Sie in der MSDN und vielen anderen Quellen.

Das .NET Framework enthält mit dem XMLWriter eine sehr einfache Klasse, die das schnelle Erstellen von XML-Dateien erlaubt. Folgende Zeilen würden ebenfalls die oben verwendete XML-Datei erstellen.

xmlWriter = New XmlTextWriter("C:\temp\test.xml", Nothing)

xmlWriter.Formatting = Formatting.Indented
xmlWriter.Indentation = 4
xmlWriter.IndentChar = " "

xmlWriter.WriteStartElement("root")

xmlWriter.WriteStartElement("Element")
xmlWriter.WriteAttributeString("id", "1")
xmlWriter.WriteElementString("Vorname", "Frank")
xmlWriter.WriteElementString("Name", "Carius")
xmlWriter.WriteElementString("Strasse", "Hegselweg")
xmlWriter.WriteElementString("PLZ", "33415")
xmlWriter.WriteElementString("Ort", "Verl")
xmlWriter.WriteEndElement()

xmlWriter.WriteStartElement("Item")
xmlWriter.WriteElementString("Vorname", "Ingrid")
xmlWriter.WriteElementString("Name", "Mantke")
xmlWriter.WriteElementString("Strasse", "Hegselweg")
xmlWriter.WriteElementString("PLZ", "33415")
xmlWriter.WriteElementString("Ort", "Verl")
xmlWriter.WriteEndElement()

xmlWriter.WriteEndElement()
xmlWriter.Close()

In PowerShell ist der umgang mit XML doch sehr viel einfacher, z.B:

get-process | export-csv process.xml

XML und VBScript

Leider gibt es eine solch einfache Klasse nicht von Hause auch für VBScript. Mit VBScript können Sie z.B.: folgendes machen

Set objDoc = CreateObject("Microsoft.XMLDOM")
Dim objchild
Set objchild = objDoc.createNode(1, "Root", "")
objDoc.documentElement.appendChild(objchild)
objDoc.Save strFile
Set objchild = Nothing

Das ganze stellt sich noch etwas komplexer da, wenn Sie mehrere Ausgaben anfügen wollen. Daher habe ich mir selbst eine VBScript-Klasse gebaut, die etwas ähnliches wie der XMLWriter und .NET bereit stellt.

xmlclass.vbs.txt
XML-Klasse mit Beispielcode

Hiermit sollte es in ihren eigenen VBScript Projekten ein einfaches sein, einfache XML-Dateien zu schreiben. Die Klasse sorgt dafür, dass die fünf Sonderzeichen, die in XML umkodiert werden müssen, auch umcodiert werden. Wenn jemand die Klasse erweitert, so dass die restlichen Funktionen ebenfalls vorhanden sind, dann würde ich gerne einen Hinweis bzw. eine Kopie erhalten.

XML und PowerShell

Viel einfacher als in VBScript kann man mit PowerShell und XML hantieren. .NET kenn ja schon eine XML-Klasse und wen Sie eine XML-Datei lesen, ändern und anpassen wollen, dann geht das direkt

# einlesen einer XML-Datei
[xml]$xmlinhalt = get-content -path dateiname.xml

# hier dann einfach die Inhalte bearbeiten, anzeigen etc

# Schreiben einer XML-Datei
$xmlinhalt.save("dateiname")

Natürlich gibt es noch viele weitere Optionen. Insbesondere zum konvertieren von Objekt-Strukturen in XML mit "Export-CLIXML etc"

Wer eine bestehende XML-Datei verarbeiten will, kann Sie einfach einlesen oder natürlich auch als Textdatei behandeln. Das ist speziell hilfreich, wenn Sie ein Stylesheet mit addieren wollen.

set-content `
   -path temp.xml `
   -value "<?xml-stylesheet type='text/xsl' href='http://www.msxfaq.net/Installs.xslt'?>

get-content `
   -path c:\temp\Installs_2007-01-18.xml `
| out-file `
   -encoding ascii `
   -append `
   -filepath temp_xml.xml

Allerdings muss man bei Stylesheets in der Hinsicht etwas aufpassen, da die XML-Dateien per Export-CliXML einen Namespace "PS" bekommen, der im Stylesheet dann mit angegeben werden muss. Hier ein Beispiel:

Get-Process `
| Export-Clixml test.xml

Die resultierende XML-Datei beginnt mit:

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/PowerShell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>System.Diagnostics.Process</T>
      <T>System.ComponentModel.Component</T>
  </Obj>
</Objs>

Entsprechend muss ein Stylesheet auch diesen "Namespace" in den Feldern voran stellen. Gut zu erkennen am "ps:Objs/ps:"

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns:ps="http://schemas.microsoft.com/PowerShell/2004/04">
<xsl:template match="/">
<html><body>
<h2><xsl:value-of select="ps:Objs/ps:Obj"/></h2>
<tr><td>TNs</td> </tr> <xsl:for-each select="ps:Objs/ps:TN"> <tr><td><xsl:value-of select="."/></td></tr> </xsl:for-each> </table> </body></html> </xsl:template></xsl:stylesheet> 

XML bearbeiten

Natürlich können Sie einfach mit einem beliebigen Texteditor eine XML-Datei bearbeiten. Allerdings ist das ziemlich fehleranfällig, da XML sehr strenge Regeln an die Form anwendet. Folgende XML-Datei enthält z.B. schon zwei Fehler.

<root>
    <child>Schon gewusst, dass 1<2 wahr ist ?</child>
</Root>

Sie sollten sehr schnell gesehen haben dass "Root" und "root" nicht übereinstimmen und das "<" Zeichen so losgelöst nicht möglich ist. für einen Parser startet ja hiermit ein neues Tag.

Um solche Fehler zu vermeiden bietet sich natürlich ein Editor an, der XML nicht nur farblich kennzeichnet, sondern sogar die Eingabe aktiv unterstützt.. Mein Favorit (und zudem kostenfrei) ist

XML Notepad 2007 by Chris Lovett of Microsoft:
http://www.microsoft.com/downloads/details.aspx?familyid=72D6AA49-787D-4118-BA5F-4F30FE913628&mg_id=10051&displaylang=en (1,5 MB)

Aber natürlich können Sie auch andere Editoren dafür hernehmen.

MSXML und HTTP

XML ist aber nicht nur ein Dateiformat,  sondern an sehr viele Dienste wie Exchange und SQL lassen sich Daten als XML-Struktur übertragen um Befehle auszuführen. Auch die Rückantworten kommen dann wieder als XML-Struktur.

Set oxmlhttp= CreateObject("Microsoft.XMLHTTP") 
oxmlhttp.Open "GET", "http://www.msxfaq.de", False 
oxmlhttp.Send 
shtml = xmlhttp.ResponseText

Das wird von Microsoft mit dem MSXML-Objekt unterstützt, welches nicht nur Dateien lesen und schreiben kann, sondern auch per HTTP schreiben und lesen. Gerade Exchange erlaubt per WebDAV sehr umfangreiche Änderungen . Hier ein Beispiele um

var objXMLHTTP = new ActiveXObject("msxml2.xmlhttp")
objXMLHTTP.Open("POST","processpage.asp",false)
objXMLHTTP.SetRequestHeader("Content-Type","application/x-www-form-URLencoded")
' hier können weitere Daten eingesetzt werden
objXMLHTTP.Send(sCommandXml); 
var sSavedDocument = this.DecodeResponse(objXMLHTTP.ResponseText)

Einen Eindruck können folgende Links geben oder eine Suche nach MSHTML, MSXML im Internet.

XML editieren

XML-Dateien sind "Text"-Dateien und können damit mit jedem Editor bearbeitet werden. Ratsam ist das aber nicht, da XML sehr streng ist und ein vergessenes Zeichen die komplette Datei unlesbar macht. Daher sollten Sie XML nur per Programmierung über entsprechende Methoden und Properties verändern oder einem Editor verwenden, der XML "versteht".

XML Notepad
http://www.microsoft.com/en-us/download/details.aspx?id=7973

CSV2XML

Wie man eine XML-Datei mit einem XSLT-Stylesheet umformatieren kann, habe ich weiter oben schon gezeigt. So kann man eine XML-Datei recht einfach in eine CSV-Datei überführen. Der Weg einer CSV-Datei in XML ist vielleicht ungewöhnlich aber mit Bordmitteln einfach möglich

Import-csv test.cxv | convertto-xml | out-flle text.xml

Allerdings ist die generierte XML-Datei alles andere als "schön", denn PowerShell macht eine XML-Datei mit PowerShell-Objekten draus.

Daher habe ich mir mal ein kleines Modul gebaut, welches eine per "import-csv" gelesene CSV-Datei über die Pipeline bekommt und hinten dann XML rauswirft..

# csv2xml.ps1
[CmdletBinding()]
param (
            [parameter(ValueFromPipeline=$True)]
            [string]$line
)

begin{
            write-verbose "CSV2XML:Start"
            $crlf = "`r`n"
            "<?xml version=`"1.0`" encoding=`"ISO-8859-15`"?>" + $crlf
            "<!-- XML File generated with CSV2XML -->" + $crlf
            "<csv2xml>" + $crlf
            [long]$count=0

}

process{
            $count++
            if ($count%100 -eq 0 ) {
                        write-verbose "Line $count"
            }
            "    <line>" + $crlf
            foreach ($property in ($_ | gm -MemberType noteproperty)) {
                        ("      <"+$property.name+">"+ $_.($property.name)+"</"+$property.name+">") + $crlf
            }
            "    </line>" + $crlf
}
end {
            "</csv2xml>" + $crlf
            write-verbose "CSV2XML:End"
}

Der Aufruf erfolgt dann dann in der Form.

import-csv .\test.csv `
| .\csv2xml.ps1 -verbose `
| out-file .\test.xml

Eine 5MB große CSV-Datei mit 6000 Zeilen wird auf einem normalen PC in ca. 20 Sekunden zu einer 12 Megabyte großen XML geschrieben. Sie können die Datei natürlich entsprechend anpassen, um Besonderheiten ihrer CSV-Datei zu berücksichtigen. Ich habe den Code erst mal nur mit normalen Zeichen getestet. Ein "<" oder ">" in den Nutzdaten wird nicht gesondert abgefangen.

Weitere Links