2011-01-12 23 views
5

Estoy tratando de escribir un XPath que seleccionará ciertos nodos que contienen una palabra específica. En este caso, la palabra es "Lockwood". La respuesta correcta es 3. Ambos caminos dame 3.XSLT Seleccionar todos los nodos que contienen una subcadena específica

count(//*[contains(./*,'Lockwood')]) 
count(BusinessLetter/*[contains(../*,'Lockwood')]) 

Pero cuando trato de la salida del texto de cada nodo específico

//*[contains(./*,'Lockwood')][1] 
//*[contains(./*,'Lockwood')][2] 
//*[contains(./*,'Lockwood')][3] 

nodo 1 termina contiene todo el texto y nodos 2 y 3 están en blanco.

¿Puede alguien decirme qué está sucediendo o qué estoy haciendo mal?

Gracias.

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="XPathFunctions.xsl"?> 
<BusinessLetter> 
<Head> 
    <SendDate>November 29, 2005</SendDate> 
    <Recipient> 
    <Name Title="Mr."> 
    <FirstName>Joshua</FirstName> 
    <LastName>Lockwood</LastName> 
    </Name> 
    <Company>Lockwood &amp; Lockwood</Company> 
    <Address> 
    <Street>291 Broadway Ave.</Street> 
    <City>New York</City> 
    <State>NY</State> 
    <Zip>10007</Zip> 
    <Country>United States</Country> 
    </Address> 
    </Recipient> 
</Head> 
<Body> 
    <List> 
    <Heading>Along with this letter, I have enclosed the following items:</Heading> 
    <ListItem>two original, execution copies of the Webucator Master Services Agreement</ListItem> 
    <ListItem>two original, execution copies of the Webucator Premier Support for Developers Services Description between Lockwood &amp; Lockwood and Webucator, Inc.</ListItem> 
    </List> 
    <Para>Please sign and return all four original, execution copies to me at your earliest convenience. Upon receipt of the executed copies, we will immediately return a fully executed, original copy of both agreements to you.</Para> 
    <Para>Please send all four original, execution copies to my attention as follows: 

<Person> 
    <Name> 
    <FirstName>Bill</FirstName> 
    <LastName>Smith</LastName> 
    </Name> 
    <Address> 
    <Company>Webucator, Inc.</Company> 
    <Street>4933 Jamesville Rd.</Street> 
    <City>Jamesville</City> 
    <State>NY</State> 
    <Zip>13078</Zip> 
    <Country>USA</Country> 
    </Address> 
    </Person> 
    </Para> 
    <Para>If you have any questions, feel free to call me at <Phone>800-555-1000 x123</Phone> or e-mail me at <Email>[email protected]</Email>.</Para> 
</Body> 
<Foot> 
    <Closing> 
    <Name> 
    <FirstName>Bill</FirstName> 
    <LastName>Smith</LastName> 
    </Name> 
    <JobTitle>VP of Operations</JobTitle> 
    </Closing> 
</Foot> 
</BusinessLetter> 
+0

Buena pregunta, +1. Vea mi respuesta para una explicación, una solución completa y fácil y una regla útil para recordar. :) –

Respuesta

10

Pero cuando trato de la salida del texto de cada nodo específico

//*[contains(./*,'Lockwood')][1] 
//*[contains(./*,'Lockwood')][2] 
//*[contains(./*,'Lockwood')][3] 

nodo 1 termina que contiene todo el texto y los nodos 2 y 3 están en blanco

Esta es una pregunta frecuente.

//SomeExpression[1] 

no es el equivalente a

(//someExpression)[1] 

El primero selecciona todos los nodos que están //SomeExpression el primer hijo de su padre.

Este último selecciona el primero (en orden de documento) de todos los nodos //SomeExpression en todo el documento.

¿Cómo se aplica esto a su problema?

//*[contains(./*,'Lockwood')][1] 

Esto selecciona todos los elementos que tienen al menos un hijo cuya cadena de valor contiene 'Lockwood' y que son el primer hijo de su padre. Los tres elementos que tienen un nodo de texto que contiene la cadena 'Lockwood' son los primeros hijos de sus padres, por lo que se seleccionan tres elementos.

//*[contains(./*,'Lockwood')][2] 

no hay ningún elemento que tiene un niño con valor de cadena que contiene la cadena 'Lockwood' y es el segundo hijo de su padre. No se seleccionan nodos.

//*[contains(./*,'Lockwood')][3] 

no hay ningún elemento que tiene un niño con valor de cadena que contiene la cadena 'Lockwood' y es el tercer hijo de su padre. No se seleccionan nodos.

Solución:

Uso:

(//*[contains(./*,'Lockwood')])[1] 
(//*[contains(./*,'Lockwood')])[2] 
(//*[contains(./*,'Lockwood')])[3] 

Cada uno de estos selecciona exactamente el n-ésimo elemento (N = {1,2,3}) seleccionados por //*[contains(./*,'Lockwood')], correspondientemente: BusinesLetter, Recipient y Body.

Recuerde:

El [] operador tiene mayor prioridad (precedencia) que el // abreviatura.

+1

+1 Buena respuesta. Formaly desde http://www.w3.org/TR/xpath/#NT-Predicate: * Un predicado filtra un conjunto de nodos con respecto a un eje para producir un nuevo conjunto de nodos *. Y esto '// * [1]' se expande a '/ descenddant-or-self :: node()/child :: * [1]' –

Cuestiones relacionadas