Как применить функцию XPath 'substring-after' - PullRequest
17 голосов
/ 02 декабря 2008

Какое выражение XPath я бы использовал, чтобы получить строку, следующую за 'HarryPotter:' для каждой книги.

т. Учитывая этот XML:

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

Я бы вернулся:

Chamber of Secrets
Prisoners in Azkabahn 

Я пробовал что-то вроде этого:

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

Я думаю, что мой синтаксис неправильный ...

Ответы [ 4 ]

22 голосов
/ 02 декабря 2008

В XPath 2.0 это можно получить одним выражением XPath:

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

Здесь мы используем очень мощную функцию XPath 2.0, заключающуюся в том, что в конце этапа определения местоположения мы можем поместить функцию, и эта функция будет применяться ко всем узлам в текущем наборе результатов.

В XPath 1.0 такой функции нет , и это невозможно сделать в одном выражении XPath.

Мы могли бы выполнить XSLT-преобразование следующим образом:

<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>  

При применении к исходному документу XML:

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

это преобразование дает желаемый результат:

Тайная комната
Заключенные в Азкабане

5 голосов
/ 02 декабря 2008

В вашем XML у вас нет пробела между Гарри Поттером, но в вашем XQuery есть пробел. Просто сделайте так, чтобы они совпадали и давали, вы получите данные обратно ...

    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
4 голосов
/ 02 декабря 2008

Выражение XPath

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

вернет набор узлов со всеми текстовыми узлами, содержащими значение «HarryPotter:». Чтобы получить название книги после HarryPotter: вам нужно пройти через этот набор узлов и извлечь эту подстроку для каждого узла. Это можно сделать с помощью substring-after, если вы используете XSLT, или с помощью Substring и IndexOf, если вы используете VB, как показано в balabaster.

0 голосов
/ 01 февраля 2015

Xpath:

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

Я совершенно новичок в этой области, но для меня это работает ...!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...