2012-09-11 19 views
9

ho bisogno di creare un'espressione XPath che fa il seguente:XPath: Default a 'nodo A', selezionare 'Nodo B', invece, se 'Nodo B' non è vuota

  • Restituisce l'elemento interno dell ' NodeA 'per impostazione predefinita
  • Restituisce l'elemento all'interno di "NodoB" se non è vuoto.

Ecco alcune XML di esempio in modo che la mia struttura di destinazione è chiaramente visibile (sto usando MS InfoPath):

<?xml version="1.0" encoding="UTF-8"?><?mso-infoPathSolution solutionVersion="1.0.0.10" productVersion="14.0.0" PIVersion="1.0.0.0" href="file:///C:\Documents%20and%20Settings\Chris\Local%20Settings\Application%20Data\Microsoft\InfoPath\Designer3\9016384cab6148f6\manifest.xsf" ?><?mso-application progid="InfoPath.Document" versionProgid="InfoPath.Document.3"?> 
<my:myFields xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-09-07T14:19:10" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xml:lang="en-us"> 
<my:NodeASection> 
    <my:NodeA>2012-09-13</my:NodeA> 
</my:NodeASection> 
    <my:NodeBSection> 
     <my:NodeBGroup> 
      <my:NodeB>2012-09-14</my:NodeB> 
     </my:NodeBGroup> 
    </my:NodeBSection> 
</my:myFields> 

Questa espressione XPath può essere utilizzato per valutare NodoB per l'esistenza di testo: boolean(//my:NodeB[(text())])

Ho sentito parlare del "Metodo Becker" ma non sono sicuro di come si possa verificare quando entrambi i nodi esistono. Sono molto nuovo per XPath e apprezzo qualsiasi aiuto che può essere offerto. espressione

risposta

15

Questo XPath restituisce Nodo B se esiste (ed ha contenuto del testo) e NodoA nell'altro caso:

//my:NodeB[text()] | //my:NodeA[text() and not(//my:NodeB[text()])] 

Se si desidera ottenere tutti i sub-elementi è possibile accodare /* dopo il nodo selezionato, ti piace questa

//my:NodeB[text()]/* | //my:NodeA[text() and not(//my:NodeB[text()])]/* 
+0

Sei la BOMBA! Ho passato tutto il giorno ieri anche a cercare di formulare quella domanda. Ho bisogno di prendere una lezione per questa roba ... l'ho adattata al mio problema un po 'più complesso. Grazie ancora! – Shrout1

1

Se è sicuro di fare affidamento sul fatto che qualsiasi NodoA arriverà prima del Nodo B nell'ordine del documento (come implica il campione), poi un'espressione XPath più semplice e molto più efficiente per selezionare l'elemento richiesto è ...

(//my:NodeA[text()]|//my:NodeB)[1] 

Quanto sopra seleziona l'elemento. Se si desidera selezionare il nodo di testo dell'elemento, quindi utilizzare invece ...

(//my:NodeA[text()]|//my:NodeB)[1]/text() 

Se non v'è alcuna relazione posizionale tra NodoA e NodoB (possono venire in qualsiasi ordine relativo), e si stanno utilizzando XPath 2.0, quindi la seguente espressione selezionerà il nodo di testo richiesti ..

(//my:NodeA[text()],//my:NodeB)[1]/text() 
3

un'espressione XPath corretta è:

(//my:NodeB[node()] | //my:NodeA[not(//my:NodeB/node())])/node() 

Poiché le condizioni nei predicati si escludono a vicenda, solo una di esse può essere true() e ciò garantisce che solo uno dei due nodi è selezionato dall'espressione all'interno delle parentesi.

Quindi, l'espressione sopra seleziona qualsiasi nodo figlio di: my:NodeB se ha figli, oppure my:NodeA - otherwize.

Qui assumiamo come dato che al massimo un elemento denominato my:NodeA e al massimo un elemento denominato my:NodeB esiste nel documento XML.

Un altro presupposto è che lo spazio dei nomi a cui è associato il prefisso my è stato "registrato" con l'analizzatore di espressioni XPath (l'implementazione XPath specifica che si sta utilizzando).

Do atto che nel documento XML fornito nessuno degli elementi my:NodeA e my:NodeB ha dei elementi figli (entrambi hanno solo un bambino nodo di testo) - quindi immagino che da "elemento" in realtà significa "nodo ".

+0

Dimitre - grazie ancora! La tua risposta sembra essere più ampiamente applicabile. Sono nuovo di tutto questo, quindi perdonami se uso erroneamente la terminologia; sto solo cercando di riprenderlo mentre me ne vado! Non so esattamente come MS InfoPath valuti XPath con lo spazio dei nomi 'mio'. La risposta di David Parsson ha funzionato bene però! Credo che il controllo [node()] potrebbe essere più ampiamente applicabile però. – Shrout1

+0

@Chris, Tutto dipende da cosa intendi per "vuoto" - e non esiste una definizione universale per questo. La risposta attualmente accettata molto probabilmente interpreta "vuoto" come non avendo un figlio nodo di testo. La mia risposta interpreta "vuoto" come non avere alcun figlio (quindi un elemento che ha altri elementi come figli, ma nessun figlio di nodo di testo è considerato non vuoto. Altre persone vorrebbero che ci sia almeno un figlio di nodo di testo che non è composto solo da caratteri di spazi vuoti.Se tu definisci rigorosamente la tua definizione di "vuoto", le persone potrebbero dare una risposta più precisa –

+0

In questa istanza controlla il testo mancante. I campi di InfoPath devono essere associati a un elemento XML (o nodo?) e quindi ci sarà sempre una struttura preesistente.In molte forme ho ripetuto tabelle o sezioni e in quell'istanza si potrebbe verificare "l'esistenza" del nodo stesso. – Shrout1

Problemi correlati