2010-06-01 8 views
5

Ich bin neu in XPath, und nach dem, was ich in einigen Tutorials über Achsen gelesen habe, frage ich mich immer noch, wie ich sie implementieren soll. Sie verhalten sich nicht so, wie ich es erwartet hatte. Ich bin besonders daran interessiert, Ahnen- und Nachkommenachsen zu verwenden.XPath-Vorgänger und -Sekender in XSL copy-of

Ich habe die folgende XML-Struktur:

<file> 
    <criteria> 
     <root>ROOT</root> 
     <criterion>AAA</criterion> 
     <criterion>BBB</criterion> 
     <criterion>CCC</criterion> 
    </criteria> 
    <format> 
     <sort>BBB</sort> 
    </format> 
</file> 

Und ich habe folgendes XSL:

<xsl:template match="/"> 
    <xsl:copy-of select="ancestor::criterion/> 
</xsl:template> 

, die nichts produziert!

erwartete ich, es zu produzieren:

<file> 
    <criteria> 
    </criteria> 
</file> 

Kann jemand erklären Vorfahren und Nachkommen Achsen mir in hilfreicher Weise als die Tutorials, die ich vorher gelesen haben?

Danke!

+0

Gute Frage (+1). Siehe meine Antwort für eine Erklärung und eine vollständige Lösung. –

Antwort

5

Und ich habe folgendes XSL:

<xsl:template match="/"> 
    <xsl:copy-of select="ancestor::criterion/> 
</xsl:template> 

, die nichts produziert!

Wie es sollte!

ancestor::criterion 

ist ein relativer Ausdruck, der bedeutet, dass er den aktuellen Knoten ausgewertet wird ausgeschaltet (durch die Schablone angepasst). Der aktuelle Knoten ist jedoch der Dokumentknoten /.

So ist das obige äquivalent zu:

/ancestor::criterion 

jedoch per Definition der Dokumentknoten / keine Eltern hat (und das heißt, keine Vorfahren), so dass diese XPath-Ausdruck auswählen keine Knoten.

ich es erwartet zu produzieren:

<file> 
    <criteria> 
    </criteria> 
</file> 

Was Sie wahrscheinlich wollte, war:

//criterion/ancestor::* 

oder

//*[descendant::criterion] 

Die letzten beiden XPath-Ausdrücke sind gleichwertig und wählen alle Elemente, die einen criterion Nachkommen haben.

schließlich die Ausgabe, die Sie wollten zu produzieren hier, ist eine mögliche Lösung:

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

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="root | criterion | format"/> 
</xsl:stylesheet> 

Wenn diese Transformation auf dem mitgelieferten XML-Dokument angelegt wird, der gewünschte Ausgang hergestellt:

<file> 
<criteria> 
</criteria> 
</file> 
+0

Vielen Dank für Ihre Antwort. // criterion/ancestor :: * und // * [descendant :: criteria] geben mir seltsame Ergebnisse, und während die vollständig codierte Lösung, die du zur Verfügung gestellt hast, funktioniert und die erwarteten Ergebnisse liefert, brauche ich immer noch eine weniger hartcodierte Lösung (oben) Lösung erfordert das Wissen von Root und Format .. aber es kann andere geben, die ich nicht kenne ..) Auch, danke für die Erklärung von Nachkommen und Vorfahren Achsen :) – developer

+0

@iHeartGreek: Warum erwarten Sie einen XPath-Ausdruck, der auswählt bestimmte Knoten, um andere Knoten zu wählen? Falls Sie ein anderes Problem haben, stellen Sie einfach eine andere Frage. Sie haben die Frage nicht gestellt, die nicht beantwortet wird. :) –

1

ancestor ist für die Auswahl von Knoten, die höher (näher an der Wurzel) im XML-Dokument sind. descendant dient zum Auswählen von Knoten, die im XML-Dokument untergeordnete Elemente (untergeordnete Elemente) enthalten.

In Ihrem Beispiel wählt ancestor::criterion nichts, weil der aktuelle Knoten / (die Wurzel des Dokuments Bedeutung - <file> in diesem Fall), wie durch match="/" angegeben. Der Wurzelknoten hat keine Vorfahren, so dass die Achse ancestor nichts tut.

Um jeden <criterion> Element zu erhalten, sollten Sie die descendant Achse verwenden:

<xsl:template match="/"> 
    <xsl:copy-of select="descendant::criterion"/> 
</xsl:template> 

oder seine Abkürzung //:

<xsl:template match="/"> 
    <xsl:copy-of select="//criterion"/> 
</xsl:template> 

, dass die folgenden zurückkehren:

<criterion>AAA</criterion> 

Verwendung eine Schleife oder eine andere Vorlage, die Sie alle drei erhalten können sie:

<xsl:template match="/"> 
    <file> 
    <xsl:apply-templates select="//criterion"/> 
    </file> 
</xsl:template> 
<xsl:template match="criterion"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

Dies liefert die folgende:

<file> 
    <criterion>AAA</criterion> 
    <criterion>BBB</criterion> 
    <criterion>CCC</criterion> 
</file> 

Wenn Sie das <file> Element erhalten möchten, auch, es ist ein bisschen komplizierter. XPath gibt Knoten an und einfache Kopien kopieren nicht die Elemente, die die von Ihnen ausgewählten Elemente enthalten. Ich kann diesen Punkt mehr klären, wenn Sie immer noch verwirrt sind.

+0

Sie sagen, dass: ' ' die folgende zurück: ' AAA' Dies ist nicht so. Das Ergebnis wird sein: ' AAA BBB CCC' –

+0

nur einen Punkt, aber 'Nachkomme :: criterion' nicht äquivalent ist zu' // criterion'; Letzteres findet alle Kriterienknoten im gesamten Dokument. Die richtige Abkürzung ist '.// Kriterium'. – Flynn1179