2012-04-02 5 views
1

Ich habe einige nicht-heirarchal Xml, die Pseudo-Struktur hat. Jedes Objekt deklariert ein übergeordnetes Objekt (mit Ausnahme des "root" -Objekts) und null oder mehr untergeordnete Elemente, verwendet jedoch statt einer verschachtelten Struktur IDs und Referenzattribute. Ich möchte dies in eine verschachtelte Struktur konvertieren.Wie kann ich mit XSLT 1.0 einer nicht-heirarchalen XML-Datei Struktur hinzufügen?

<document> 
    <object id="6" children="12,15"/> 
    <object id="12" parent="6" children="13,18"/> 
    <object id="13" parent="12" children="14,16,17"/> 
    <object id="14" parent="13"/> 
    <object id="15" parent="6" children="21,22"/> 
    <object id="16" parent="13"/> 
    <object id="17" parent="13"/> 
    <object id="18" parent="12" children="23,25"/> 
    <object id="19" parent="23"/> 
    <object id="21" parent="15"/> 
    <object id="22" parent="15"/> 
    <object id="23" parent="18" children="19,24"/> 
    <object id="24" parent="23"/> 
    <object id="25" parent="18"/> 
</document> 

Für die Aufzeichnung enthält das eigentliche Dokument auch Objektdefinitionen, die die Objekte auch in einem Attribut, ähnlich einer Klasse verweisen, aber ich brauche den Namen des Elements aus der Definition von wiederum Referenz-ID abzurufen. Irgendwann im Prozess konvertiere ich die Namen jedes "Objekts" in "Vorlage" oder "Unterabschnitt". Wenn es Dinge vereinfacht, kann ich diese Operation nach dem Anwenden der Struktur durchführen. Ich habe auch eine Tokenize- "Funktion" für das Children-Attribut, da ich XSLT 1.0 verwende, das nicht integriert ist.

So zum Beispiel oben ich diese Ausgabe möchte:

<document> 
    <object id="6"> 
     <object id="12"> 
      <object id="13"> 
       <object id="14"/> 
       <object id="16"/> 
       <object id="17"/> 
      </object> 
      <object id="18"> 
       <object id="23"> 
        <object id="19"/> 
        <object id="24"/> 
       </object> 
       <object id="25"/> 
      </object> 
     </object> 
     <object id="15"> 
      <object id="21"/> 
      <object id="22"/> 
     </object> 
    </object> 
</document> 

Bitte beachten Sie, dass diese Objekt Elemente andere Informationen enthalten, Attribute, Daten usw. Diese zur Vereinfachung des Beispiels entfernt wurde, aber kann dem Problem eine Komplexitätsebene hinzufügen.

Wenn möglich möchte ich dies auf eine elegante und erweiterbare Weise tun. Ich bin nicht gezwungen, sondern würde lieber XSL 1.0 verwenden (damit es in die vorhandene Server-Software integriert werden kann).

Vielen Dank an alle, die mir helfen oder mich in die richtige Richtung weisen können!

+0

Diese Frage ist sehr zweideutig: 1). Kein vollständiges XML-Dokument bereitgestellt (nur ein minimales, aber vollständiges Dokument ist erforderlich); 2). Es gibt sowohl '' und '' - es scheint mir, dass nur ein Name generiert werden muss, oder es sollte eine Erklärung geben, wann 'generiert werden soll Thema und wann "Element" generiert werden soll. Bitte bearbeiten Sie die Frage und geben Sie die fehlenden Daten/Erläuterungen an. –

+0

OK Dimitre, ich habe respektvoll meine Frage gestellt. Nun, meine Frage an Sie ist, können Sie mir helfen, oder haben Sie einfach das Board kontrolliert? – kcstrong

+0

kcstrong: Wenn ich nicht daran interessiert bin, zu helfen, warum sollte ich meine Zeit damit verschwenden, um Klärung zu bitten? Ich fange an, in ein paar Minuten zu arbeiten - wird wahrscheinlich in 10 Stunden Zeit für Ihre Frage haben.Ich hatte eine nicht schlechte Lösung, bevor ich zu den Unklarheiten kam, die mich daran hinderten, diese Lösung zu veröffentlichen. –

Antwort

0

Ohne die vollständige XSLT, könnten Sie Ihre Transformation wie folgt strukturieren: Grundsätzlich würde die Vorlage für Bücher eine Anwendung Vorlagen für Kapitel aufrufen, und die Vorlage für Kapitel würde gelten-Vorlagen für Themen usw. Der Schlüssel Hier wird die ID aus dem übergeordneten Element in eine Variable eingefügt, sodass Sie sie in nachfolgenden Anwen- dungsschablonenaufrufen verwenden können, um die untergeordneten Elemente zu finden.

<document> 
    <xsl:apply-templates select="/document/book" /> 
</document> 

<xsl:template match="/document/book"> 
    <xsl:variable name="bookid"> 
     <xsl:value-of select="@id"/> 
    </xsl:variable> 
    <xsl:element name="book"> 
     <xsl:attribute name="id"> 
     <xsl:value-of select="@id"/> 
     </xsl:attribute> 
     <xsl:apply-templates select="/document/chapter[@parent=$bookid]" /> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="/document/chapter"> 
    Template for chapter would be replicated from the book template above 
    . 
    . 
    . 
</xsl:template> 
+0

Vielen Dank für Ihre Antwort. Es sieht so aus, als ob dies der einzige Weg ist. Ich hatte es versucht und gescheitert, aber ich hatte gehofft, dass es immer noch eine Kombination von Methoden gäbe, die es mir erlauben würden, Elemente rekursiv auf die n-te Ebene zu verschachteln, ohne sie explizit zu deklarieren. Dies würde mich daran hindern, den Code zu ändern, wenn jemand einen der Elementnamen ändern und mir erlauben würde, den Code wiederzuverwenden, um ähnliche Dokumente vom selben System zu verarbeiten. Prost! – kcstrong

+0

Es sieht so aus, als ob du die Frage jetzt komplett geändert hast, also macht meine ursprüngliche Antwort keinen Sinn mehr. Ich würde Ihnen jedoch empfehlen, wenn Sie sich Sorgen über Änderungen am Quelldokument machen, sollten Sie in Betracht ziehen, ein Schema zu veröffentlichen. Auf diese Weise können Sie vor dem Ausführen der Umwandlung für das Schema validieren, und Sie können sicherstellen, dass die Ergebnisse einheitlich sind, solange das Eingabedokument das vordefinierte Schema erfüllt. Selbst eine generische Lösung kann beschädigt werden, wenn das Quelldokument ausreichend geändert wird. – javram

0

Diese kurze und einfache, vollständige Transformation:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:key name="kChildren" match="object" use="@parent"/> 

<xsl:template match="/*"> 
    <document> 
    <xsl:apply-templates select="*[not(@parent)]"/> 
    </document> 
</xsl:template> 

<xsl:template match="object"> 
    <object id="{@id}"> 
    <xsl:apply-templates select="key('kChildren', @id)"/> 
    </object> 
</xsl:template> 
</xsl:stylesheet> 

wenn auf dem mitgelieferten XML-Dokument angelegt:

<document> 
    <object id="6" children="12,15"/> 
    <object id="12" parent="6" children="13,18"/> 
    <object id="13" parent="12" children="14,16,17"/> 
    <object id="14" parent="13"/> 
    <object id="15" parent="6" children="21,22"/> 
    <object id="16" parent="13"/> 
    <object id="17" parent="13"/> 
    <object id="18" parent="12" children="23,25"/> 
    <object id="19" parent="23"/> 
    <object id="21" parent="15"/> 
    <object id="22" parent="15"/> 
    <object id="23" parent="18" children="19,24"/> 
    <object id="24" parent="23"/> 
    <object id="25" parent="18"/> 
</document> 

erzeugt das gewünschte, korrekte Ergebnis:

<document> 
    <object id="6"> 
     <object id="12"> 
      <object id="13"> 
       <object id="14"/> 
       <object id="16"/> 
       <object id="17"/> 
      </object> 
      <object id="18"> 
       <object id="23"> 
        <object id="19"/> 
        <object id="24"/> 
       </object> 
       <object id="25"/> 
      </object> 
     </object> 
     <object id="15"> 
      <object id="21"/> 
      <object id="22"/> 
     </object> 
    </object> 
</document> 

Erläuterung: Korrekte Verwendung von Schlüsseln.