Tom2 (der authentifizierte): Extrakt aus DOMDocument

Hi Leute

Ich arbeite erst seit kurzem mit XML und XSL, was inzwischen auch recht gut funktioniert. Jetzt soll ich jedoch eine XML-Datei mit dem DOM weiterverarbeiten und weiss nicht genau wie man das macht. Kann mir jemand helfen?

Ich arbeite mit mit ASP und VBScript auf einem IIS und für DOM verwende ich die Microsoft XML Core Services (MSXML2.DOMDocument). Die Struktur meines Dokuments sieht so aus:

<Root>
  <Hauptgruppe Typ="1">
    <Untergruppe id="1">
      <Eintrag id="1" />
      <Eintrag id="2" />
      <Eintrag id="3" />
    </Untergruppe>
    <Untergruppe id="2">
      <Eintrag id="1" />
      <Eintrag id="2" />
    </Untergruppe>
  </Hauptgruppe>
  <Hauptgruppe Typ="2">
    <Untergruppe id="1">
      <Eintrag id="1" />
      <Eintrag id="2" />
    </Untergruppe>
  </Hauptgruppe>
</Root>

Ich möchte nun für jeden Eintrag eine eigene Datei erstellen. Wenn die Datei nur ein Eintrag-Element hat, dann klappt das mit meinem XSL-Dokument schon sehr gut. Ich möchte also einen Eintrag und all dessen Elternelemente, nicht aber die ganzen Brüder und Schwestern selektieren. Gib es hierfür ein einfaches Standard-Verfahren oder muss ich mir die Elemente selbst zusammenkratzen?

Mit oXML.getElementsByTagName("Eintrag") kann ich alle Einträge selektieren und mit getAttribute komm ich auch an die IDs ran. In der DOM Reference von Microsoft hab ich was von context gelesen, jedoch krig ich das nicht zum Laufen (manchmal "unknown property", manchmal keine Fehlermeldung, die Ausgabe wird einfach abgebrochen). Zudem habe ich das Problem, dass ich mit getElementsByTagName alle Einträge unabhängig von Haupt- und Untergruppe selektiere. Normalerweise ist in einem solchen XML-Dokument nur eine Hauptgruppe drin, ich möchte das ganze jedoch möglichst flexibel halten. Wer stand schon vor einem ähnlichen Problem und kann mir einen Hinweis geben?

Und noch was allgemeineres: Wie finde ich heraus, ob ich ein DOMDocument, ein DOMNode oder eine DOMList zurückerhalte und welche Eigenschaften und Methoden diese wirklich unterstützen? Aus der Microsoft-Referenz ist das nicht genau ersichtlich.

Gruss & Dank

Tom2

  1. Ich bins nochmals. Hab jetzt geschafft, auf die parentNodes zuzugreifen und so die Dateinamen zu erzeugen (in VBScript):

    Set oEntryList = oXML.getElementsByTagName("Eintrag")
        For Each oEntry In oEntryList
          sPath = oEntry.parentNode.parentNode.getAttribute("Typ")
          sPath = sPath & "" & oError.parentNode.getAttribute("id")
          sPath = sPath & "\entry_" & oError.getAttribute("id") & ".html"
          ' aus oEntry-Element vollständiges XML-Dokument machen (?)
          ' Datei öffnen
          ' oEntry-Dokument mit XSL tranformieren
          ' Ausgabe speichern
        Next

    Wie mach ich nun aus dem oEntry-Element ein vollständiges XML-Dokument? Am einfachsten ist es natürlich, von Hand <Root><Hauptgruppe><Untergruppe> drum zu packen, jedoch müsste ich dann extra alle Attribute nochmals auslesen. Wenn neue Attribute hinzu kommen muss ich dann aber wieder die Funktion anpassen, was ich lieber nicht möchte. Gibt es eine bessere Möglichkeit?

    Gruss & Dank

    Tom2

    1. Hallo,

      Ich bins nochmals. Hab jetzt geschafft, auf die parentNodes zuzugreifen und so die Dateinamen zu erzeugen (in VBScript):

      Set oEntryList = oXML.getElementsByTagName("Eintrag")
          For Each oEntry In oEntryList
            sPath = oEntry.parentNode.parentNode.getAttribute("Typ")
            sPath = sPath & "" & oError.parentNode.getAttribute("id")
            sPath = sPath & "\entry_" & oError.getAttribute("id") & ".html"
            ' aus oEntry-Element vollständiges XML-Dokument machen (?)
            ' Datei öffnen
            ' oEntry-Dokument mit XSL tranformieren
            ' Ausgabe speichern
          Next

      Wie mach ich nun aus dem oEntry-Element ein vollständiges XML-Dokument? Am einfachsten ist es natürlich, von Hand <Root><Hauptgruppe><Untergruppe> drum zu packen, jedoch müsste ich dann extra alle Attribute nochmals auslesen. Wenn neue Attribute hinzu kommen muss ich dann aber wieder die Funktion anpassen, was ich lieber nicht möchte. Gibt es eine bessere Möglichkeit?

      Ich kann kein VBScript / kenne die Microsoft XML Core Services nicht, aber allgemein gibt es im DOM die Methode createDocument beim implementation-Objekt, was am Document-Objekt hängt (also schematisch document.implementation.createDocument). Außerdem gibt es document.createDocumentFragment, das erzeugt dann etwas Dokument-ähnliches, das sich möglicherweise transformieren lässt.

      Soweit ich weiß erzeugt man Dokumente in ASP/VBScript standardmäßig so:
      Server.CreateObject("Microsoft.XMLDOM")
      (In JScript new ActiveXObject("MSXML2.DOMDocument").)
      In einem so erzeugtes Dokument kannst du die Elemente Hauptgruppe und Untergruppe erzeugen und den oEntry-Elementknoten importieren. Das geht in DOM über die Methode document.importNode(), MSXML kennt aber meines Wissens nur Elementknoten.cloneNode().

      (Man korrigiere/ergänze mich.)

      Mathias

      1. Hallo Mathias

        Ich kann kein VBScript / kenne die Microsoft XML Core Services nicht, aber allgemein gibt es im DOM die Methode createDocument beim implementation-Objekt, was am Document-Objekt hängt (also schematisch document.implementation.createDocument).

        Danke für den Hinweis. Das werde ich mir mal genauer anschauen.

        Außerdem gibt es document.createDocumentFragment, das erzeugt dann etwas Dokument-ähnliches, das sich möglicherweise transformieren lässt.

        Wenn ich das richtig sehe gibt mir diese Methode einen DOMNode oder eine DOMNodeList zurück. Ich muss dieses Fragment nicht selbst erzeugen, ich kann es mit getElementsByTagName() oder selectNodes() extrahieren. Transformieren kann ich dieses leider nicht mit meinem Stylesheet, weil ich dieses nur für komplette Dokumente verwenden möchte. Oder ist das so üblich, XSL auf Fragmente anzuwenden?

        In einem so erzeugtes Dokument kannst du die Elemente Hauptgruppe und Untergruppe erzeugen und den oEntry-Elementknoten importieren. Das geht in DOM über die Methode document.importNode(), MSXML kennt aber meines Wissens nur Elementknoten.cloneNode().

        Mein Problem ist, dass ich einen Knoten ohne Unterknoten, jedoch mit all den Attributen kopieren möchte. Aber die Attribute sind ja eigentlich auch Knoten, darum geht's wohl nicht.

        Ich hab's jetzt so gelöst:
        Einer Funktion namens getDOMParents(ByRef oDOMElement, ByRef sXML) übergebe ich den Eintrags-Knoten und dessen XML-Code. Die Funktion schaut ob oDOMElement.parent.nodeName nicht gleich "#document" ist, weil wir dann beim Root-Element angelangt sind. Ist dem nicht so, so wird das parent-Element mit all seinen Attributen um den XML-String gepackt und die Funktion nochmals für das Eltern-Element aufgerufen. Zum Schluss wird noch die XML-Deklaration an den String angehängt und fertig ist mein Dokument.

        Jetzt hab ich wieder Zeit mich mit den Stylesheets rumzuschlagen... Kennt jemand einen guten Validator / Parser für XML-Dateien aller Art? Mein IE schluckt irgendwie alles und der auf dem Server hat noch nie was von brauchbaren Fehlermeldungen gehört ;-).

        Gruss und Dank für die Hilfe

        Tom2