Получение атрибута с использованием XPath

344

Учитывая структуру XML, например, так:

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book>
  <title lang="eng">Harry Potter</title>
  <price>29.99</price>
</book>

<book>
  <title lang="eng">Learning XML</title>
  <price>39.95</price>
</book>

</bookstore>

Как я могу получить значение lang(где langнаходится engв названии книги), для первого элемента?

GurdeepS
источник
2
очень хорошая ссылка при использовании xpaths test-able.blogspot.ie/2016/04/xpath-selectors-cheat-sheet.html

Ответы:

473

Как я могу получить значение lang (где lang = eng в названии книги) для первого элемента?

Используйте :

/*/book[1]/title/@lang

Это значит :

Выберите langатрибут элемента title, который является дочерним по отношению к первому bookдочернему элементу верхнего элемента XML-документа.

Чтобы получить только строковое значение этого атрибута, используйте стандартную функцию XPathstring() :

string(/*/book[1]/title/@lang)
Димитр Новатчев
источник
3
@AbhishekAsthana, в результате оценки выражения XPath получается именно строковое значение langатрибута. Если атрибут не содержит квадратных скобок, они не будут частью результата вычисления выражения XPath. Я предполагаю, что они добавляются (неподходящим) инструментом, который вы используете.
Димитр Новачев
6
да, я разобрался с проблемой ... вот как мыло это отображает soapUI, но эти скобки не используются, когда я использую значение xpath. Я видел это много времени. Проблема не в инструменте ... между креслом и клавиатурой.
Абхишек Астана
4
@KorayTugay, выражение XPath /*/book[1]/title/@lang выбирает набор узлов из 0 или более узлов атрибутов, в то время как выражение XPath string(/*/book[1]/title/@lang)при оценке выдает строковое значение этого набора узлов - и это строковое значение первого (в порядке документа) узел из этого набора узлов.
Димитр Новатчев
4
@KorayTugay, нет, первое выражение выбирает , не «возвращает» - набор узлов, и этот набор узлов не является строкой. Узел не является строкой - узел является узлом в дереве . XML-документ - это дерево узлов. lang="eng"является лишь одним из многих текстовых представлений узла атрибута, который имеет имя «lang», не принадлежит пространству имен и имеет строковое значение в виде строки «eng»
Dimitre Novatchev 22.10.14
1
@Vladimir, если v соответствует пространству имен uri, скажем: «my: vvv», то можно создать на хосте используемого механизма XPath отображение, связывающее myPrefix (может быть v, но не обязательно) с тем же пространством имен -ури "мой: vvv". И тогда атрибут будет выбран с помощью: title / @ myPrefix: lang. Как создается такое отображение, зависит от реализации, и нужно прочитать в документации хоста механизма XPath. Это делается особым образом в .NET, а по-другому, скажем, в саксонской. Если у вас нет такого сопоставления, используйте: title / @ * [name () = 'v: lang']
Dimitre Novatchev
47

Спасибо! Это решило аналогичную проблему с атрибутом данных внутри Div.

<div id="prop_sample" data-want="data I want">data I do not want</div>

Используйте этот xpath: //*[@id="prop_sample"]/@data-want

Надеюсь, это поможет кому-то еще!

smulldino
источник
6

Вы можете попробовать ниже шаблон xPath,

  XPathExpression expr = xPath.compile("/bookstore/book/title[@lang='eng']")
Sharath
источник
5
Это выберет любой элемент заголовка XML в / bookstore / book, имеющий атрибут lang со значением eng, а не со значением lang. то есть он выбирает список элементов, а не один атрибут
JFK
2

Вы также можете получить его по

string(//bookstore/book[1]/title/@lang)    
string(//bookstore/book[2]/title/@lang)

хотя, если вы используете XMLDOM с JavaScript, вы можете написать что-то вроде

var n1 = uXmlDoc.selectSingleNode("//bookstore/book[1]/title/@lang");

и n1.textдаст вам значение"eng"

Винод Шривастав
источник
2

ты можешь использовать:

(//@lang)[1]

это означает, что вы получаете все атрибуты узлов с именем, равным «lang», и получаете первый.

starcwl
источник
0

Вот фрагмент получения значения атрибута "lang" с XPath и VTD-XML.

import com.ximpleware.*;
public class getAttrVal {
    public static void main(String s[]) throws VTDException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("input.xml", false)){
            return ;
        }
        VTDNav vn = vg.getNav();
        AutoPilot ap = new AutoPilot(vn);
        ap.selectXPath("/bookstore/book/title/@lang");
        System.out.println(" lang's value is ===>"+ap.evalXPathToString());
    }
}
VTD-XML-автор
источник
0

Если вы используете PostgreSQL, это верный способ получить его. Это всего лишь предположение, когда у вас есть столбец TITLE и PRICE таблицы книг с заполненными данными. Вот запрос

SELECT xpath('/bookstore/book/title/@lang', xmlforest(book.title AS title, book.price AS price), ARRAY[ARRAY[]::TEXT[]]) FROM book LIMIT 1;
Royce
источник