I am creating a tool that executes xpath 1.0 requests on XHTML documents. Requiring to use a namespace prefix in a query kills me. The request is as follows:
html/body/div[@class='contents']/div[@class='body']/
div[@class='pgdbbyauthor']/h2[a[@name][starts-with(.,'Quick')]]/
following-sibling::ul[1]/li/a
(all in one line)
... which is bad enough, except that it is xpath 1.0, I need to use an explicit namespace prefix for each QName, so it looks like this:
ns1:html/ns1:body/ns1:div[@class='contents']/ns1:div[@class='body']/
ns1:div[@class='pgdbbyauthor']/ns1:h2[ns1:a[@name][starts-with(.,'Quick')]]/
following-sibling::ns1:ul[1]/ns1:li/ns1:a
To set up a query, I do something like this:
var xpathDoc = new XPathDocument(new StringReader(theText));
var nav = xpathDoc.CreateNavigator();
var xmlns = new XmlNamespaceManager(nav.NameTable);
foreach (string prefix in xmlNamespaces.Keys)
xmlns.AddNamespace(prefix, xmlNamespaces[prefix]);
XPathNodeIterator selection = nav.Select(xpathExpression, xmlns);
But I want xpathExpression to use the default implicit namespace.
Is there a way to convert an unmanaged xpath expression after it is written to introduce a namespace prefix for each element name in the request?
, - , . , "parent::" "previous-sibling::". . , " finagle ".
?
. , xpath, , nav.Select(), . - :
string FixupWithDefaultNamespace(string expr)
{
string s = expr;
s = Regex.Replace(s, "^(?!::)([^/:]+)(?=/)", "ns1:$1");
s = Regex.Replace(s, "/([^/:]+)(?=/)", "/ns1:$1");
s = Regex.Replace(s, "::([A-Za-z][^/:*]*)(?=/)", "::ns1:$1");
s = Regex.Replace(s, "\\[([A-Za-z][^/:*\\(]*)(?=[\\[\\]])", "[ns1:$1");
s = Regex.Replace(s, "/([A-Za-z][^/:]*)(?!<::)$", "/ns1:$1");
s = Regex.Replace(s, "^([A-Za-z][^/:]*)$", "ns1:$1");
s = Regex.Replace(s, "([-A-Za-z]+)\\(([^/:\\.,\\)]+)(?=[,\\)])", "$1(ns1:$2");
return s;
}
, . - xpath, , , , ns1. , , Regex.Replace , xpath ?