Eine XML-Hierarchie reduzieren

(Auszug aus "XSLT Kochbuch" von Sal Mangano)

Problem

Sie haben ein Dokument mit Elementen, die tiefer geschachtelt sind, als Ihnen lieb ist. Sie wollen den Baum daher reduzieren.

Lösung

Falls Ihr Ziel einfach darin besteht, eine Reduzierung vorzunehmen, ohne die Informationen zu berücksichtigen, die von der tieferen Struktur kodiert sind, müssen Sie eine überschreibende Kopie anwenden. Das überschreibende Template muss die Elemente erfassen, die Sie verwerfen wollen, und Templates anwenden, ohne zu kopieren.

Betrachten Sie die folgende Eingabe, die Leute in zwei Kategorien teilt – gewerkschaftlich organisierte (»union«) und nicht gewerkschaftlich organisierte (»salaried«) Angestellte:

<people>
  <union>
    <person>
      <firstname>Warren</firstname>
      <lastname>Rosenbaum</lastname>
      <age>37</age>
      <height>5.75</height>
    </person>
    <person>
      <firstname>Dror</firstname>
      <lastname>Seagull</lastname>
      <age>28</age>
      <height>5.10</height>
    </person>
    <person>
      <firstname>Mike</firstname>
      <lastname>Heavyman</lastname>
      <age>45</age>
      <height>6.0</height>
    </person>
    <person>
      <firstname>Theresa</firstname>
      <lastname>Archul</lastname>
      <age>37</age>
      <height>5.5</height>
    </person>
  </union>
  <salaried>
    <person>
      <firstname>Sal</firstname>
      <lastname>Mangano</lastname>
      <age>37</age>
      <height>5.75</height>
    </person>
    <person>
      <firstname>Jane</firstname>
      <lastname>Smith</lastname>
      <age>28</age>
      <height>5.10</height>
    </person>
    <person>
      <firstname>Rick</firstname>
      <lastname>Winters</lastname>
      <age>45</age>
      <height>6.0</height>
    </person>
    <person>
      <firstname>James</firstname>
      <lastname>O'Riely</lastname>
      <age>33</age>
      <height>5.5</height>
    </person>
  </salaried>
</people>

Dieses Stylesheet verwirft einfach die zusätzliche Struktur:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="copy.xslt"/>
  <xsl:output method="xml" version="1.0" encoding="UTF-8"/>
  <xsl:template match="people">
    <xsl:copy>
      <!--Elternelemente der person-Elemente verwerfen -->
      <xsl:apply-templates select="*/person" />
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Diskussion

Im Allgemeinen ist es gut, wenn man in einem Dokument eine zusätzliche Struktur hat, weil das Dokument dadurch normalerweise leichter mit XSLT verarbeitet werden kann. Zu viel Struktur jedoch bläht das Dokument auf und erschwert das Verständnis. Menschen bevorzugen es meist, Beziehungen anhand der Textorganisation zu durchschauen und nicht durch zusätzlichen syntaktischen Ballast.

Das folgende Beispiel zeigt, dass die zusätzliche Struktur nicht überflüssig ist, sondern weitere Informationen kodiert. Falls Sie trotz der Reduzierung Informationen über die Struktur erhalten wollen, sollten Sie wahrscheinlich ein Attribut oder ein Kindelement erzeugen, um die Informationen aufzunehmen.

Dieses Stylesheet erzeugt ein Attribut:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="copy.xslt"/>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
  <!--Verwerfen der Elternelemente der person-Elemente -->
  <xsl:template match="*[person]">
    <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="person">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="class">
        <xsl:value-of select="local-name(..)"/>
      </xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Diese Variante erzeugt ein Element:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:import href="copy.xslt"/>
  <xsl:strip-space elements="*"/>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
  <!--Verwerfen der Elternelemente der person-Elemente -->
  <xsl:template match="*[person]">
    <xsl:apply-templates/>
  </xsl:template>
  <xsl:template match="person">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:element name="class">
        <xsl:value-of select="local-name(..)"/>
      </xsl:element>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Sie können xsl:strip-space und indent="yes" beim xsl:output-Element einsetzen, damit die Ausgabe keine Whitespace-Lücke enthält, wie hier gezeigt:

<people>
  ...
  <person>
    <class>union</class>
    <firstname>Warren</firstname>
    <lastname>Rosenbaum</lastname>
    <age>37</age>
    <height>5.75</height>
   </person>
                                      <!-- Hier ist die Whitespace-Lücke! -->

  <person>
    <class>salaried</class>
    <firstname>Sal</firstname>
    <lastname>Mangano</lastname>
    <age>37</age>
    <height>5.75</height>
  </person>
  ...
</people>

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2006 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT Kochbuch" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O'Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de