XPath find all matches C# XmlDocument

◇◆丶佛笑我妖孽 提交于 2021-02-07 19:14:42

问题


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.


回答1:


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




回答2:


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




回答3:


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 + "')]"




回答4:


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


来源:https://stackoverflow.com/questions/9087893/xpath-find-all-matches-c-sharp-xmldocument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!