2012-03-30 4 views
1

Ich bin völlig unbekannt mit xslt, also bitte entschuldigen Sie, wenn das eine dämliche Frage ist. Ich muss eine Variable deklarieren und es auf einen von 2 möglichen Knoten in der XML zeigen, abhängig davon, welche von ihnen tatsächlich existiert. Ich versuche Folgendes:Zuweisen eines Knotens zu einer xsl: -Variable mit Hilfe eines Tests

<xsl:variable name="DealNode"> 
    <xsl:choose> 
     <xsl:when test="/AllResponse/Deals/Deal"><xsl:copy-of select="/AllResponse/Deals/Deal"/></xsl:when> 
     <xsl:otherwise><xsl:copy-of select="/AllResponse/BookDeals/BookDeal"/></xsl:otherwise> 
    </xsl:choose> 
</xsl:variable> 

Dies scheint zu funktionieren, in dem DealNode scheint zu sein, was ich erwarte. Allerdings, wenn ich jetzt mache:

<xsl:variable name="TradeNode" select="$DealNode/Trades/Trade"/> 

TradeNode bleibt leer. Was mache ich falsch?

Probe xml:

<AllResponse> 
    <Deals> 
     <Deal> 
      <Trades> 
       <Trade> 
       </Trade> 
      </Trades> 
     </Deal> 
    </Deals> 
</AllResponse> 
+0

Arbeiten Sie in XSLT 1 oder 2? –

+0

Sorry, sollte gesagt haben, dass seine xslt 1 .. – StevieG

+0

@StevieG: Es könnte nützlich sein, zu bemerken, dass die derzeit akzeptierte Antwort eher problematisch ist. Für weitere Informationen lesen Sie bitte meine Antwort. –

Antwort

2

Ein Ansatz, die Variable zu definieren, ist wie folgt:

<xsl:variable name="DealNode" select="(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1]"/> 

, dass die Vereinigung der beiden ausgewählten Knoten-Sets bildet und nimmt die erste Knoten in dieser Vereinigung, so dass, wenn der erste Ausdruck einen Knoten auswählt, der Knoten genommen wird, wenn der erste Ausdruck nichts auswählt, dann wird der erste Knoten genommen, der durch den zweiten Ausdruck ausgewählt wurde.

+0

Funktioniert ein Vergnügen, vielen Dank! – StevieG

+0

Sorry, aber das würde bei einer Sequenz funktionieren - die Vereinigung von zwei * Knoten-Sets * ist ein neues Knoten-Set, bei dem die Knoten (per Definition) in der Reihenfolge der Dokumente sind. Daher wählt '($ ns1 | $ ns2) [1]' im allgemeinen Fall nicht den ersten Knoten von '$ ns1' - stattdessen wählt dies den ersten Knoten (in Dokumentreihenfolge) der Vereinigung der beiden Knotengruppen aus - Dies kann ein Knoten sein, der zu '$ ns' gehört, oder ein Knoten, der zu' $ ns2' gehört. Bitte korrigieren. –

+0

-1, weil die Antwort eine nicht zutreffende Aussage und im Allgemeinen eine falsche Lösung enthält, die Lerner von XPath verwirren und in die Irre führen könnte. –

0

XSLT1 nicht vollständig ergebnisBaumFragmente unterstützen. Um zu tun, was Sie versuchen, erfordert .

Auch selbst in XSLT2 die korrekte XPath ist $DealNode/Deal/Trades/Trade

3

Die derzeit akzeptierte Antwort hat ein ernstes Problem. Wenn sein XPath-Ausdruck gegen das folgende XML-Dokument ausgewertet:

<AllResponse> 
    <BookDeals> 
     <BookDeal> 
      <Trades> 
       <Trade> 
       </Trade> 
      </Trades> 
     </BookDeal> 
    </BookDeals> 
    <Deals> 
     <Deal> 
      <Trades> 
       <Trade> 
       </Trade> 
      </Trades> 
     </Deal> 
    </Deals> 
</AllResponse> 

dann in der Antwort auf die Ansprüche Gegenteil, der bereitgestellte XPath-Ausdruck:

(/AllResponse/Deals/Deal | /AllResponse/BookDeals/BookDeal)[1] 

nicht die wählen erstes Argument der Union, aber genau das Gegenteil (das 2. Argument).

Der Grund dafür ist, dass das Ergebnis der Vereinigungsoperation immer nach der Dokumentreihenfolge ihrer Knoten sortiert ist - mit anderen Worten, eine Knotenmenge ist eine Menge und keine Folge.

Hier ist eine richtige 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="/"> 
    <xsl:variable name="vDealNode" select= 
     "/*/Deals/Deal | /*[not(Deals/Deal)]/BookDeals/BookDeal"/> 

    <xsl:copy-of select="$vDealNode"/> 
</xsl:template> 
</xsl:stylesheet> 

wenn diese Transformation auf dem obigen XML-Dokument, das gewünschte, korrekte Ergebnis (der Knoten, der das erste Argument der Union Operator) angewendet wird, und das Ergebnis dieser Auswahl ausgewählt wird ausgegeben:

<Deal> 
    <Trades> 
     <Trade/> 
    </Trades> 
</Deal> 

Erläuterung: die korrekten Gen ral Ausdruck zu verwenden, wenn wir $cond$ns1, wenn eine Bedingung true() und $ns2 auszuwählen, auswählen möchten, wenn $cond falsch ist, ist:

$ns1[$cond] | $ns2[not($cond)] 

In unserem konkreten Fall:

$ns1 ist /*/Deals/Deal,

$ns2 ist /*/BookDeals/BookDeal

und

$cond ist boolean(/*/Deals/Deal)

diese in den allgemeinen Ausdruck über Einsetzen und Verkürzung:

/*/Deals/Deal[/*/Deals/Deal]

zu:

/*/Deals/Deal

wir den Ausdruck kommen uns ed in dieser Antwort:

/*/Deals/Deal | /*[not(Deals/Deal)]/BookDeals/BookDeal 
+1

Ich fand diese Antwort funktionierte für mich (mit XSLT 1.0), während die angenommene Antwort nicht. –

+0

@ B.Mo, Gern geschehen. –

Verwandte Themen