Yesterday I implemented something like xml parsing in my application. The requirements were:
- Data is send to the application in form of xml using Web Service
- End-user should be able to extract some granular data out of the xml
And here comes XPath. I added some configuration mechanism to my app so the end-user can provide xpath queries and save them in database. My WCF Service that looks exactly like an ordinary web service receives the xml data, searches for the XPath queries that should be run on the data, executes them and stores the results in the database in name-value pair table. This is the simple description of the behavior.
The code that is used to evaluate the XPath query on the xml data is below:
public string EvaluateXPath(Stream source, string xpath)
{
XPathDocument document = new XPathDocument(source);
XPathNavigator navigator = document.CreateNavigator();
XPathExpression query = navigator.Compile(xpath);
string result = (string)navigator.Evaluate(query);
return result;
}
As you can see there is XPathNavigator.Evaluate(string) method called that returns either string, bool, decimal or XPathNodeIterator.
So long everything is clear. I had some propblems with the above code and XPath. I must explain myself: I am not an XPath guru. I use tools for XSLT mapping and I do not need to know all the XPath syntax.
Here goes my problem:
I expected that EvaluateXpath("/book/title", stream) where the stream looks like that:
<book>
<title>XPath Adventures</title>
</book>
will be evaluated to a string "XPath Adventures". But it is not. In fact it is evaluated to XPathNodeIterator as it actually selects some nodes. Each time I tried to do something with my XPath i got InvalidCastException as I tried to cast the XPathNodeIterator to a string. I remind you: I am not an XPath guru. It took me longer that I thought as I tried to figure out by myself (without reading XPath documenatation) what should I type there to get what I need. I failed. I had to find it in some tutorial. Proper syntax of XPath when you want to evaluate string value is below:
string(/book/title)
I learned my lesson to NOT to be too smart.