问题
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