Использование XPath в SelectSingleNode: получение отдельного элемента из XML, если он присутствует
Мой XML выглядит так:
<?xml version=\"1.0\"?>
<itemSet>
<Item>one</Item>
<Item>two</Item>
<Item>three</Item>
.....maybe more Items here.
</itemSet>
Некоторые из отдельных Элементов могут присутствовать или отсутствовать. Скажем, я хочу извлечь элемент <Item>
два </Item>
, если он присутствует. Я пробовал следующие XPaths (в С#).
-
XMLNode node = myXMLdoc.SelectSingleNode("/itemSet[Item='two']")
--- Если присутствует элемент 2, он возвращает мне только первый элемент. Может быть, этот запрос просто указывает на первый элемент в itemSet, если у него есть Item value two где-то в качестве дочернего. Правильно ли эта интерпретация?
Итак, я попробовал:
-
XMLNode node = myXMLdoc.SelectSingleNode("/itemSet[Item='two']/Item[1]")
--- Я прочитал этот запрос как, вернул мне первый элемент <Item>
в itemSet, который имеет value = 'two'. Правильно ли я?
Это возвращает только первый элемент. Что я делаю не так?
В обоих случаях, используя братьев и сестер, я могу пересекать дочерние узлы и добираться до двух, но это не то, на что я смотрю. Также, если два отсутствует, SelectSingleNode возвращает null. Таким образом, сам факт, что я получаю успешный возврат node, указывает на присутствие элемента два, так что, если бы я хотел, чтобы логический тест на chk присутствовал на двух, любой из вышеперечисленных XPaths был бы достаточным, но мне на самом деле нужна полная элемент <Item>two</Item>
в качестве моего возврата node.
[Мой первый вопрос здесь, и мой первый раз работающий с веб-программированием, поэтому я только что изучил вышеупомянутые XPaths и связанные с ним материалы xml прямо сейчас из прошлых вопросов в SO. Будьте осторожны и дайте мне знать, являюсь ли я doofus или нарушаю любые правила сообщества. Спасибо.]
Ответы
Ответ 1
Я думаю, вы хотите:
myXMLdoc.SelectSingleNode("/itemSet/Item[text()='two']")
Другими словами, вам нужен элемент, который содержит текст из двух, а не itemSet
, содержащий его.
Вы также можете использовать одну точку, чтобы указать контекст node, в вашем случае:
myXMLdoc.SelectSingleNode("/itemSet/Item[.='two']")
EDIT: разница между .
и text()
заключается в том, что .
означает "этот node", а text()
означает "все текстовые node дочерние элементы этого node". В обоих случаях сравнение будет проводиться против "строковой стоимости" LHS. Для элемента node строковое значение представляет собой "конкатенацию строковых значений всех текстовых node потомков элемента node в порядке документа" и для набора текстовых узлов сравнение проверит, любой текст node равен тому, который вы тестируете.
Поэтому не имеет значения, когда содержимое элемента имеет только один текст node, но предположим, что у нас было:
<root>
<item name="first">x<foo/>y</item>
<item name="second">xy<foo/>ab</item>
</root>
Тогда выражение XPath "root/item[.='xy']
" будет соответствовать первому элементу, но "root/item[text()='xy']
" будет соответствовать второму.