XPath oddity
-
For something I'm working on, I want to test a given XmlElement with a provided XPath predicate to determine whether or not it's the droid node I'm looking for.
public static bool
IsMatch
(
this System.Xml.XmlElement Element
,
string Predicate
)
{
return ( Element.SelectSingleNode ( "self::node()[" + Predicate + "]" ) != null ) ;
}I wasted an hour trying to get
.[predicate]
to work.System.Xml.XmlDocument doc = new System.Xml.XmlDocument() ;
doc.LoadXml ( "<Foo Bar='Baz' />" ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( "." ).OuterXml ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( "self::node()[@Bar='Baz']" ).OuterXml ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( "self::*[@Bar='Baz']" ).OuterXml ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( ".[@Bar='Baz']" ).OuterXml ) ;<Foo Bar="Baz" />
<Foo Bar="Baz" />
<Foo Bar="Baz" />
System.Xml.XPath.XPathException: '.[@Bar='Baz']' has an invalid token.The book I have says
.
is equivalent toself::node()
, but that's not true,.
returns a node, whereasself::node()
returns a node-set, and you can only apply a predicate to a node-set. :sigh: Of course, if you know of a way to test a node that uses neither SelectSingleNode nor SelectNodes, I'd be glad to see it.You'll never get very far if all you do is follow instructions.
-
For something I'm working on, I want to test a given XmlElement with a provided XPath predicate to determine whether or not it's the droid node I'm looking for.
public static bool
IsMatch
(
this System.Xml.XmlElement Element
,
string Predicate
)
{
return ( Element.SelectSingleNode ( "self::node()[" + Predicate + "]" ) != null ) ;
}I wasted an hour trying to get
.[predicate]
to work.System.Xml.XmlDocument doc = new System.Xml.XmlDocument() ;
doc.LoadXml ( "<Foo Bar='Baz' />" ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( "." ).OuterXml ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( "self::node()[@Bar='Baz']" ).OuterXml ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( "self::*[@Bar='Baz']" ).OuterXml ) ;
System.Console.WriteLine ( doc.DocumentElement.SelectSingleNode ( ".[@Bar='Baz']" ).OuterXml ) ;<Foo Bar="Baz" />
<Foo Bar="Baz" />
<Foo Bar="Baz" />
System.Xml.XPath.XPathException: '.[@Bar='Baz']' has an invalid token.The book I have says
.
is equivalent toself::node()
, but that's not true,.
returns a node, whereasself::node()
returns a node-set, and you can only apply a predicate to a node-set. :sigh: Of course, if you know of a way to test a node that uses neither SelectSingleNode nor SelectNodes, I'd be glad to see it.You'll never get very far if all you do is follow instructions.
PIEBALDconsult wrote:
Of course, if you know of a way to test a node that uses neither SelectSingleNode nor SelectNodes, I'd be glad to see it.
How about this?
public static bool IsMatch(this System.Xml.XmlElement element, string predicate)
{
return element.CreateNavigator().Matches("*[" + predicate + "]");
}If you're going to be re-using the same predicate for a lot of elements, you might want to pre-compile it[^]:
public static bool IsMatch(this System.Xml.XmlElement element, XPathExpression compiledPredicate)
{
return element.CreateNavigator().Matches(compiledPredicate);
}
...
var compiledPredicate = XPathExpression.Compile("*[" + predicate + "]");
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
PIEBALDconsult wrote:
Of course, if you know of a way to test a node that uses neither SelectSingleNode nor SelectNodes, I'd be glad to see it.
How about this?
public static bool IsMatch(this System.Xml.XmlElement element, string predicate)
{
return element.CreateNavigator().Matches("*[" + predicate + "]");
}If you're going to be re-using the same predicate for a lot of elements, you might want to pre-compile it[^]:
public static bool IsMatch(this System.Xml.XmlElement element, XPathExpression compiledPredicate)
{
return element.CreateNavigator().Matches(compiledPredicate);
}
...
var compiledPredicate = XPathExpression.Compile("*[" + predicate + "]");
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Thanks, I'll try that too and maybe do some performance comparisons. Performance really isn't an issue with my current usage -- about forty elements being checked with a predicate provided on the command-line. Your second implementation might make for the basis of an enumerator. :thumbsup:
You'll never get very far if all you do is follow instructions.