2012-09-11 11 views
9

Necesito crear una expresión XPath que hace lo siguiente:XPath: Por defecto a 'nodo A', seleccione 'Nodo B' en lugar si Nodo B no está vacío

  • Devuelve el elemento interior de ' NodeA 'de forma predeterminada
  • Devuelve el elemento dentro de' NodeB 'si no está vacío.

Aquí es un poco de XML de ejemplo para que mi estructura objetivo puede verse claramente (estoy 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> 

Esta expresión XPath se puede utilizar para evaluar el Nodo B de la existencia del texto: boolean(//my:NodeB[(text())])

He oído hablar del "Método Becker" pero no estoy seguro de cómo se aplica cuando ambos nodos existen. Soy muy nuevo en XPath y aprecio cualquier ayuda que pueda ofrecerse. expresión

Respuesta

15

Este XPath devuelve Nodo B si existe (y tiene contenido de texto) y NodoA en el otro caso:

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

Si desea obtener todos los sub-elementos que se pueden anexar /* después de que el nodo seleccionado, como esto

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

¡Eres la BOMBA! Pasé todo el día ayer incluso tratando de formular esa pregunta. Hombre Necesito tomar una clase para esto ... Acabo de adaptarlo a mi problema un poco más complejo. ¡Gracias de nuevo! – Shrout1

1

Si es seguro que confiar en el hecho de que de ninguna NodoA vendrá antes Nodo B en el orden del documento (como lo implica su muestra), a continuación, una expresión XPath simple y mucho más eficiente para seleccionar el elemento requerido es ...

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

Lo anterior selecciona el elemento. Si desea seleccionar el nodo de texto del elemento, a continuación, utilizar en su lugar ...

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

Si no existe una relación de posición entre NodoA y Nodo B (que pueden venir en cualquier orden relativa), y están utilizando XPath 2.0, a continuación, la siguiente expresión seleccionará el nodo de texto requerido ..

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

Una expresión XPath correcta es:

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

Como las condiciones en los predicados son mutuamente excluyentes, solo una de ellas puede ser true() y esto garantiza que solo uno de los dos nodos es seleccionado por la expresión entre corchetes.

Por lo tanto, la expresión anterior selecciona cualquier nodo que sea un elemento secundario de: my:NodeB si tiene hijos, o my:NodeA - otherwize.

Aquí suponemos que, como máximo, existe un elemento llamado my:NodeA y como máximo un elemento denominado my:NodeB en el documento XML.

Otra suposición es que el espacio de nombres al que está vinculado el prefijo my ha sido "registrado" con el evaluador de expresiones XPath (la implementación específica de XPath que está utilizando).

Ten en cuenta que en el documento XML siempre y cuando ninguno de los elementos my:NodeA y my:NodeB tiene ningún elemento hijos (ambos tienen sólo un niño nodo de texto) - así que supongo que por "elemento" en realidad se refiere a "nodo ".

+0

Dimitre - gracias de nuevo! Su respuesta parece ser más ampliamente aplicable. Soy nuevo en todo esto, así que discúlpeme si uso la terminología de forma incorrecta; ¡Estoy tratando de recogerlo mientras voy! No sé exactamente cómo MS InfoPath evalúa XPath con el espacio de nombres 'my'. ¡La respuesta de David Parsson funcionó bien! Creo que la comprobación de [node()] podría ser más amplia, sin embargo. – Shrout1

+0

@Chris, todo depende de lo que quieras decir con "vacío", y no hay una definición universal para esto. La respuesta actualmente aceptada probablemente interprete "vacío" como no tener un hijo de nodo de texto. Mi respuesta interpreta "vacío" como no tener ningún elemento secundario (por lo tanto, un elemento que tiene otros elementos como secundarios, pero ningún elemento secundario de texto-nodo se considera no vacío. Otras personas desearían que haya al menos un elemento secundario de texto-nodo no se compone solo de caracteres de espacios en blanco. Si define estrictamente su definición de "vacío", entonces la gente podría dar una respuesta más precisa. –

+0

En este caso, está comprobando si falta texto. Los campos de InfoPath deben estar vinculados a un elemento XML (o nodo?) y así siempre habrá una estructura preexistente. En muchas formas tengo tablas o secciones repetitivas y en esa instancia se podría verificar la "existencia" del nodo en sí. – Shrout1

Cuestiones relacionadas