XPath найти все совпадения C# XmlDocument
Я пытаюсь выяснить, как найти все совпадения строки в XmlDocument
.
XmlNodeList results
= document.SelectNodes("Products/Product/fn:matches(.,'" + SearchWord + "')");
Я пытаюсь сравнить innerText
продукта.
Приведенный выше пример не работает, но я думаю, что мой способ использования функций XPath очень неправильный.
4 ответа:
Оцените это выражение XPath 1.0 (знаете ли вы, что
matches()
является функцией XPath 2.0 и не поддерживается в .NET):Products/Product/descendant::*[contains(text(), 'YourSearchWord')]
При этом выбираются все элементы, имеющие текстовый узел-потомок, содержащий строку
'YourSearchWord'
и являющиеся потомками элементаProduct
, являющегося дочерним элементом элементаProducts
, являющегося дочерним элементом текущего (контекстного) узла.Вы можете составить выражение XPath с помощью :
string.Format("Products/Product/descendant::*[contains(text(), '{0}')]", SearchWord )
Однако, если
SearchWord
получается из пользовательского ввода, то это рекомендуется никогда не включать его в скелетную строку, как описано выше, чтобы избежать инъекции XPath.Если это так, то рекомендуется использовать предварительно скомпилированное выражение XPath, в котором на пользовательский ввод будет ссылаться переменная и значение этой переменной будет использоваться из контекста оценки XPath.
Более подробную информацию о том, как предотвратить инъекцию XPath, можно найти в этом разделе ответ :
Допустим, у вас есть следующий xml
<Names> <Name> <FirstName>John</FirstName> <LastName>Smith</LastName> </Name> <Name> <FirstName>James</FirstName> <LastName>White</LastName> </Name> </Names>
Для получения всех узлов используйте выражение XPath / Names / Name. Первая косая черта означает, что узел должен быть корневым узлом. Метод SelectNodes возвращает коллекцию XmlNodeList, которая будет содержать узлы. Чтобы получить значение подузла, вы можете просто проиндексировать XmlNode с именем узла: xmlNode ["FirstName"].Внутренний текст.
XmlDocument xml = new XmlDocument(); xml.LoadXml(myXmlString); // suppose that myXmlString contains "<Names>...</Names>" XmlNodeList xnList = xml.SelectNodes("/Names/Name"); foreach (XmlNode xn in xnList) { string firstName = xn["FirstName"].InnerText; string lastName = xn["LastName"].InnerText; Console.WriteLine("Name: {0} {1}", firstName, lastName); }
Вывод:
Имя: Джон Смит Имя: Джеймс Уайт
Используйте это в качестве примера / отправной точки. спасибо
Если я правильно понял ваш вопрос, вы можете использовать следующее:
"Products/Product/[.='" + SearchWord + "']"
Или использовать такие функции, как
contains()
,starts-with()
, илиnormalize-space()
(обрезает и заменяет последовательный пробел одним пробелом)
"Products/Product/[contains(normalize-space(.), '" + SearchWord + "')]"
Из ответа на Этот дублирующий вопрос:
Данное выражение вычисляется как логическое, а не как набор узлов. Я предполагаю, что вы хотите проверить, соответствует ли имя проекта параметризованному текст. В этом случае вам нужно написать
//ErrorTable/ProjectName[text()='{0}']
Это дает вам список всех узлов (nodeset), соответствующих данному состояние. Этот список может быть пустым, и в этом случае c#-выражение в ваш образец вернет значение null.
Как запоздалая мысль: вы может использовать исходное выражение xpath, но не с SelectSingleNode, а с Evaluate, вот так:
(bool)xmlDocument.CreateNavigator().Evaluate(String.Format("//ErrorTable/ProjectName/text()='{0}'", projectName));