2009-12-01 5 views
8

Actualmente estoy tratando el siguiente XPathcómo hacer funcionar la función xpath de normalize-space()?

//tr[normalize-space(td/text())='User Name'] 

para obtener toda la tr que contiene un TD que contiene 'User Name' o 'User Name' o ' User Name ' pero no su trabajo y no sé lo que está mal con la consulta :(
los datos que quiero encontrar es el siguiente formato

<tr><td>User Name</td></tr> 
<tr><td>User  Name</td></tr> 
<tr><td> User Name </td></tr> 

Entonces, ¿cuál es el formato adecuado para escribir esta consulta XPath?

Editar: que no parezca funcionar si los datos están en el formato siguiente

<tr><td>x</td><td>User Name</td></tr> 
<tr><td>x</td><td>y</td><td>User  Name</td></tr> 
<tr><td>x</td><td>y</td><td>z</td><td> User Name </td></tr> 

por lo que ahora ¿Cómo puedo escribir la consulta XPath?
nota: "// tr [normalize-space (td/text()) = 'Nombre de usuario']" no funcionará
pero "// tr/td [normalize-space (text()) = 'Nombre de usuario ']" funcionará (pero quiero conseguir el TR y no el elemento td)

+0

Por favor, muestre una muestra de sus datos de entrada, comenzando con ''. –

+0

@Pavel Minaev: Hecho :) – Karim

+0

Todo se ve bien a primera vista. Sospecho que el problema no está en la consulta, sino en cómo usar los resultados. ¿Puede mostrar la consulta en contexto? Si es XSLT, el código XSLT que lo llama y usa los resultados, si es código C# directamente, entonces ese código. –

Respuesta

26

Ahora que ha editado la pregunta, tiene sentido. Vamos a considerar esta entrada:

<tr><td>x</td><td>User Name</td></tr> 

y la consulta que no trabaja:

//tr[normalize-space(td/text()) = 'User Name'] 

Ahora, td/text() significa "seleccionar todos los nodos de texto niño de todos los niños td nodos del nodo actual". En este caso, esto producirá un conjunto de nodos que consta de dos nodos de texto, x y User Name.

Ahora llama al normalize-space() en ese conjunto de nodos. El tipo del único argumento de normalize-space() es string?. Desde un conjunto de nodos no es una cadena, las conversiones patada en, por section 3.2 de XPath 1.0 recomendación:

Un argumento se convierte en tipo cadena como si llamando a la función de cadena().

Ahora vamos a ver el definition de cadena() en la sección 4.2:

Un conjunto de nodos se convierte en una cadena mediante la devolución de la cadena de valor del nodo en el conjunto de nodos eso es primero en el pedido de documento. Si el conjunto de nodos está vacío, se devuelve una cadena vacía.

En nuestro ejemplo, el primer nodo "en el orden del documento" es el nodo de texto x, por lo que es el que se utilizará; el segundo nodo es ignorado Por lo tanto, terminas llamando al normalize-space('x'). Naturalmente, esto no se comparará con 'Nombre de usuario'.Para realizar este trabajo, el uso:

//tr[td[normalize-space(text()) = 'User Name']] 

Esto puede ser transcrito como "seleccionar todos tr nodos que tienen niños td nodos, el primer nodo hijo text() de los cuales tiene un valor de cadena normalizada de User Name" - que es lo que querer. Por otra parte, se puede simplificar esto a:

//tr[td[normalize-space() = 'User Name']] 

Desde un no-argumento normalize-space() se aplicará al nodo actual (que será td), y procesar todos los nodos de texto dentro.

1

Esto funciona bien aquí:

XmlDocument xmlDoc = new XmlDocument(); 
xmlDoc.LoadXml(@" 
    <table> 
     <tr><td>User Name</td></tr> 
     <tr><td> User Name </td></tr> 
     <tr><td> User Name </td></tr> 
    </table>"); 

Console.WriteLine(
    xmlDoc.SelectNodes(
     "//tr[td[normalize-space(.) = 'User Name']]").Count); // shows "3" 

¿puede usted por favor, actualice su pregunta con una muestra XML real?

+0

el archivo actual es grande, por lo que no es posible subirlo. pero la muestra es como la que tienes, pero no funciona para mí – Karim

+0

no necesitas cargar todo el archivo, solo una pequeña pieza donde tienes problemas –

+0

, así que descubrí cuál era el problema y actualicé mi muestra – Karim

Cuestiones relacionadas