2008-12-02 20 views
16

¿Cuál es la expresión XPath que usaría para obtener la cadena siguiente a 'HarryPotter:' para cada libro.Cómo aplicar la función XPath 'substring-after'

es decir. Teniendo en cuenta este XML:

<bookstore> 
<book> 
    HarryPotter:Chamber of Secrets 
</book> 
<book> 
    HarryPotter:Prisoners in Azkabahn 
</book> 
</bookstore> 

Me gustaría volver:

Chamber of Secrets 
Prisoners in Azkabahn 

He intentado algo como esto:

/bookstore/book/text()[substring-after(. , 'HarryPotter:')] 

Creo que mi sintaxis es incorrecta ...

Respuesta

22

En XPath 2.0 este puede ser producido por una sola expresión XPath:

            /*/*/substring-after(., 'HarryPotter:')

Aquí estamos utilizando la característica muy potente de XPath 2.0 que en el extremo de una ruta de pasos de ubicación podemos poner una función y esta función se aplicará a todos los nodos en el conjunto de resultados actual.

En XPath 1.0 no existe tal característica y esto no se puede lograr en una expresión XPath.

Podríamos realizar una transformación XSLT como el siguiente:

 
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text"/> 

    <xsl:template match="/"> 
     <xsl:for-each select="/*/*[substring-after(., 'HarryPotter:')]"> 
     <xsl:value-of select= 
     "substring-after(., 'HarryPotter:')"/> 
     <xsl:text>&#xA;</xsl:text> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

cuando se aplica sobre el documento XML original:

 
<bookstore> 
    <book> HarryPotter:Chamber of Secrets </book> 
    <book> HarryPotter:Prisoners in Azkabahn </book> 
</bookstore> 

esta transformación produce el resultado deseado:

Cámara de Secretos
Prisioneros en Azkabahn

+0

Por el contrario, XPath 1.0 * does * tiene substring-after: http://www.w3.org/TR/xpath/#function-substring- after –

+6

@ Josh-Stodola, ¿Dónde dije que no tiene la función substring-after()? XPath 1.0 * no permite * que se especifique una función como paso de ubicación, si esto es subserie posterior() o cualquier otra función. Por favor, ¡revierte su * downvote * incorrecto! –

+6

Josh no sabe quién es Dimitre :) – grantwparks

5

En tu XML no tienes espacio entre Harry Potter pero en tu XQuery tienes espacio. Sólo que corresponda y listo, obtendrá datos de nuevo ...

Dim xml = <bookstore> 
        <book>HarryPotter:Chamber of Secrets</book> 
        <book>HarryPotter:Prisoners in Azkabahn</book> 
        <book>MyDummyBook:Dummy Title</book> 
       </bookstore> 

    Dim xdoc As New Xml.XmlDocument 
    xdoc.LoadXml(xml.ToString) 

    Dim Nodes = xdoc.SelectNodes("/bookstore/book/text()[substring-after(., 'HarryPotter:')]") 

    Dim Iter = Nodes.GetEnumerator() 
    While Iter.MoveNext 
     With DirectCast(Iter.Current, Xml.XmlNode).Value 
      Console.WriteLine(.Substring(.IndexOf(":") + 1)) 
     End With 
    End While 
+0

lo siento - esa cadena tenía un espacio por error ... Lo he arreglado ahora. Hace la manipulación de cadenas en VB (no en XPath).Estoy tratando de usar la expresión XPath es obtener todo después de la cadena 'HarryPotter:' en cada nodo seleccionado. ¿Algunas ideas? –

+0

aquí no hay XQuery ... solo un XPath. Además, el uso de substring-after() dentro de un predicado es claramente un error por parte del OP, no algo que queremos perpetuar. – LarsH

4

La expresión XPath

/bookstore/book/text()[substring-after(. , 'HarryPotter:')] 

devolverá un conjunto de nodos con todos los nodos de texto que contienen el valor "HarryPotter:". Para que el título del libro sea exitoso con "HarryPotter:" debe pasar por este conjunto de nodos y buscar esa subcadena para cada nodo. Esto se puede hacer con substring-after si está usando XSLT o con Substring e IndexOf si está usando VB como lo muestra balabaster.

0

XPath:

substring-after(//book, 'Advertised:') 

estoy totalmente nueva en esta zona, pero para mí, funciona ...!