XPath 查找所有匹配项 C# XmlDocument

发布于 2025-01-01 04:24:28 字数 275 浏览 1 评论 0原文

我试图弄清楚如何在 XmlDocument 中查找字符串的所有匹配项。

XmlNodeList results 
      = document.SelectNodes("Products/Product/fn:matches(.,'" + SearchWord + "')");

我正在尝试比较产品的innerText

虽然上面的例子不起作用,但我想我使用 XPath 函数的方式是非常错误的。

I am trying to figure out how to find all matches of string in a XmlDocument.

XmlNodeList results 
      = document.SelectNodes("Products/Product/fn:matches(.,'" + SearchWord + "')");

Im trying to compare the innerText of Product.

The above example don't work though, but I guess my way of using XPath functions are very wrong.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心凉 2025-01-08 04:24:29

评估此 XPath 1.0 表达式(您知道 matches() 是一个 XPath 2.0 函数,.NET 不支持):

Products/Product/descendant::*[contains(text(), 'YourSearchWord')]

这会选择所有具有文本的元素 -包含字符串 'YourSearchWord' 的节点子级,并且是 Product 元素的后代,该元素是 Products 元素的子级,而 Products 元素是当前的孩子(上下文)节点。

您可以使用以下内容组成 XPath 表达式

string.Format("Products/Product/descendant::*[contains(text(), '{0}')]", 
              SearchWord )

但是,如果 SearchWord 是从用户输入中获取的,建议永远不要将其包含在上述骨架字符串中,以免 XPath 注入将被避免。

如果是这种情况,建议的方法是使用预编译的 XPath 表达式,其中用户输入将作为变量引用,并且将从 XPath 计算上下文中使用该变量的值。

有关如何防止 XPath 注入的更多详细信息,请参阅此答案

https://stackoverflow .com/a/6393690/36305

Evaluate this XPath 1.0 expression (did you know matches() is an XPath 2.0 function and isn't supported in .NET):

Products/Product/descendant::*[contains(text(), 'YourSearchWord')]

This selects all elements that have a text-node-child that contains the string 'YourSearchWord' and that are descendents of a Product element that is a child of a Products element that is a child of the current (context) node.

You can compose the XPath expression with:

string.Format("Products/Product/descendant::*[contains(text(), '{0}')]", 
              SearchWord )

However, if SearchWord is obtained from user input, it is recommended never to include it in a skeletal string as above, so that XPath injection will be avoided.

If this is the case, the recommended method is to have a precompiled XPath expression in which the user input will be referenced as a variable and the value of this variable will be consumed from the XPath evaluation context.

More details how to prevent an XPath injection can be found in this answer:

https://stackoverflow.com/a/6393690/36305

谎言月老 2025-01-08 04:24:29

假设您有以下 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"].InnerText。

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);
}

输出为:

姓名:John Smith
姓名:James White

以此作为示例/起点。谢谢

Lets say you have the following xml

<Names>
    <Name>
        <FirstName>John</FirstName>
        <LastName>Smith</LastName>
    </Name>
    <Name>
        <FirstName>James</FirstName>
        <LastName>White</LastName>
    </Name>
</Names>

To get all nodes use XPath expression /Names/Name. The first slash means that the node must be a root node. SelectNodes method returns collection XmlNodeList which will contain the nodes. To get value of sub node you can simply index XmlNode with the node name: xmlNode["FirstName"].InnerText.

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);
}

The output is:

Name: John Smith
Name: James White

use this as an example / starting point. thanks

千笙结 2025-01-08 04:24:29

如果我正确理解您的问题,您可以使用以下内容:

"Products/Product/[.='" + SearchWord + "']"

或使用 contains() 等函数code>、starts-with()normalize-space()(修剪并用一个空格替换连续的空格)

"Products/Product/[contains (规范化空间(.), '" + 搜索词 + "')]"

If I understand your question correctly, you can use the following:

"Products/Product/[.='" + SearchWord + "']"

or use functions such as contains(), starts-with(), or normalize-space() (trims and replaces consecutive white space with one space)

"Products/Product/[contains(normalize-space(.), '" + SearchWord + "')]"

赴月观长安 2025-01-08 04:24:29

从答案

给定的表达式计算结果为布尔值,而不是节点集。我假设
您想检查 ProjectName 是否等于参数化的
文本。在这种情况下你需要写

//ErrorTable/ProjectName[text()='{0}']

这将为您提供与给定匹配的所有节点(节点集)的列表
健康)状况。该列表可能为空,在这种情况下,C# 表达式
您的示例将返回 null。

事后诸葛亮:您可以使用原始的 xpath 表达式,但是
不是使用 SelectSingleNode,而是使用 Evaluate,如下所示:

(bool)xmlDocument.CreateNavigator().Evaluate(String.Format("//ErrorTable/ProjectName/text()='{0}'", projectName));

From the answer to this duplicate question:

The expression given evaluates to a boolean, not a node-set. I assume
you want to check whether the ProjectName equals the parametrized
text. In this case you need to write

//ErrorTable/ProjectName[text()='{0}']

This gives you a list of all nodes (a nodeset) matching the given
condition. This list may be empty, in which case the C#-Expression in
your sample will return null.

As an afterthought: You can use the original xpath expression, but
not with SelectSingleNode, but with Evaluate, like this:

(bool)xmlDocument.CreateNavigator().Evaluate(String.Format("//ErrorTable/ProjectName/text()='{0}'", projectName));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文