2009-07-23 7 views
1

Wir haben XML-Dokumente, die viele markierte Knoten wie isProduct, isActive, isMandatory enthalten, wobei der Knotentext True oder False sein kann.Generic Xml Dokumentmanipulation

Es ist erforderlich, um die Dokumente zu manipulieren und ihre Struktur zu behalten, aber den oben genannten Knoten in eine verbale Darstellung umwandeln wie unten:

<isProduct>True</ isProduct > ===> <Type>Product<Type> 
<isProduct>False</ isProduct > ===> <Type/> 

Und das gleiche für andere Flagge Knoten.

Wir suchen eine erweiterbare und skalierbare Lösung, die nach der Bereitstellung mit minimaler Reibung konfiguriert werden kann.

Durch erweiterbar; wir meinen, dass es mehr Fälle geben wird; wie 2 Flags, die einen Status darstellen; d. h. isEmployee und isCustomer werden im Dokument verwendet, um 4 verschiedene benannte Dinge darzustellen .; Daher sollten die 4 möglichen Kombinationen nur in eine Zeichenfolge wie "Mitarbeiter", "Kunde", "Kunde-Mitarbeiter" oder "Keine" übersetzt werden.

Durch skalierbar; wir meinen, dass es verwendet werden kann, um ein beliebiges XML-Dokument ohne ein vorheriges Verständnis seines Schemas und ohne Beschränkung der Dokumentgröße zu verarbeiten.

Wir verstehen, dass dies mit XSLT getan werden kann, können wir eine XSLT schreiben, die ein beliebiges Dokument akzeptiert und das gleiche Dokument mit zusätzlichen Knoten erzeugt, die hinzugefügt oder aktualisiert werden?

+0

was also, wenn ein Knoten ' Wahre' sowie 'hat getan werden sollteWahr '? –

Antwort

2

eine Eingabe wie folgt aus der Annahme:

<gizmo> 
    <isProduct>True</isProduct> 
    <isFoo>False</isFoo> 
    <isBar>True</isBar> 
</gizmo> 

Der generische Ansatz wäre:

<xsl:template match="gizmo"> 
    <xsl:copy> 
    <xsl:apply-templates select="*" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="*[substring(local-name(), 1, 2) = 'is']"> 
    <Type> 
    <xsl:if test=". = 'True'"> 
     <xsl:value-of select="substring-after(local-name(), 'is')" /> 
    </xsl:if> 
    </Type> 
</xsl:template> 

Was produziert:

<gizmo> 
    <Type>Product</Type> 
    <Type /> 
    <Type>Bar</Type> 
</gizmo> 

Ein noch allgemeineren Ansatz nutzt eine (stark) modifizierte Identität verwandeln:

<!-- the identity template... well, sort of --> 
<xsl:template match="node() | @*"> 
    <xsl:copy> 
    <!-- all element-type children that begin with 'is' --> 
    <xsl:variable name="typeNodes" select=" 
     *[substring(local-name(), 1, 2) = 'is'] 
    " /> 

    <!-- all other children (incl. elements that don't begin with 'this ' --> 
    <xsl:variable name="otherNodes" select=" 
     @* | node()[not(self::*) or self::*[substring(local-name(), 1, 2) != 'is']] 
    " /> 

    <!-- identity transform all the "other" nodes --> 
    <xsl:apply-templates select="$otherNodes" /> 

    <!-- collapse all the "type" nodes into a string --> 
    <xsl:if test="$typeNodes"> 
     <Type> 
     <xsl:variable name="typeString"> 
      <xsl:apply-templates select="$typeNodes" /> 
     </xsl:variable> 
     <xsl:value-of select="substring-after($typeString, '-')" /> 
     </Type> 
    </xsl:if> 
    </xsl:copy> 
</xsl:template> 

<!-- this collapses all the "type" nodes into a string --> 
<xsl:template match="*[substring(local-name(), 1, 2) = 'is']"> 
    <xsl:if test=". = 'True'"> 
    <xsl:text>-</xsl:text> 
    <xsl:value-of select="substring-after(local-name(), 'is')" /> 
    </xsl:if> 
</xsl:template> 

<!-- prevent the output of empty text nodes --> 
<xsl:template match="text()"> 
    <xsl:if test="normalize-space() != ''"> 
    <xsl:value-of select="." /> 
    </xsl:if> 
</xsl:template> 

Die oben nimmt jede XML-Eingabe zu löschen und gibt die gleiche Struktur, nur Elemente <is*> genannt werden zu einer einzigen <Type> kollabierten Knoten als Strich getrennte Zeichenfolge:

<!-- in --> 
<foo> 
    <fancyNode /> 
    <gizmo> 
    <isProduct>True</isProduct> 
    <isFoo>False</isFoo> 
    <isBar>True</isBar> 
    </gizmo> 
</foo> 

<!-- out --> 
<foo> 
    <fancyNode /> 
    <gizmo> 
    <Type>Product-Bar</Type> 
    </gizmo> 
</foo> 
+0

Die Kopiervorlage entfernt auch alle Attribute aus XML-Dokumenten. – mkoeller

+0

Ja, ich weiß. Ich wollte einen Hinweis darauf geben, wie ich die "interessanten" Knoten in meinem ersten Beispiel auswählen und behandeln soll. Ich habe eine verallgemeinerte Lösung als zweiten Weg hinzugefügt, um mehr von dem zu tun, was das OP beschrieben hat. – Tomalak

1

Hier ist eine Lösung in XSLT zur TransformationIdentität basiert:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*"/> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="isProduct"> 
    <xsl:choose> 
     <xsl:when test=". = 'True'"><Type>Product</Type></xsl:when> 
     <xsl:otherwise><Type/></xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Also, wie wird das mit dem Knoten isEmployee umgehen? –

+0

Fügen Sie entweder eine ähnliche Vorlage hinzu, die "isEmployee" entspricht, oder erstellen Sie die angegebene Vorlage wie in Tomalaks Antwort. – mkoeller