2

I have this XML code

<diffgr:diffgram xmlns:msdata='urn:schemas-microsoft-com:xml-msdata' xmlns:diffgr='urn:schemas-microsoft-com:xml-diffgram-v1' FID='004'>
<Data>
   <users name='peter' UID='10003' diffgr:hasChanges='modified'/>
</Data>
</diffgr:diffgram>

I can get the name attribute by doing:

SelectSingleNode("/*/Data/*/@name");

and then print the value of that name. But I want the value of the attribute diffgr:hasChanges

I tried to do similar

SelectSingleNode("/*/Data/*/@diffgr:hasChanges");

But when trying to print the value, I get error saying

    Unhandled Exception:
System.Xml.XPath.XPathException: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.
  at MS.Internal.Xml.XPath.CompiledXpathExpr.get_QueryTree () <0x41689000 + 0x0003f> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Evaluate (System.Xml.XPath.XPathExpression expr, System.Xml.XPath.XPathNodeIterator context) <0x41688e20 + 0x0007b> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Evaluate (System.Xml.XPath.XPathExpression expr) <0x41688df0 + 0x0001a> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Select (System.Xml.XPath.XPathExpression expr) <0x41688d70 + 0x0001b> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Select (System.String xpath) <0x41684000 + 0x00026> in <filename unknown>:0 
  at System.Xml.XmlNode.SelectNodes (System.String xpath) <0x416839a0 + 0x00038> in <filename unknown>:0 
  at System.Xml.XmlNode.SelectSingleNode (System.String xpath) <0x41683950 + 0x00017> in <filename unknown>:0 
  at isoTopix.MyTest.Main (System.String[] args) [0x00018] in /home/tito/isoTopixSecurity/isoCode/console/tito.cs:28 
[ERROR] FATAL UNHANDLED EXCEPTION: System.Xml.XPath.XPathException: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.
  at MS.Internal.Xml.XPath.CompiledXpathExpr.get_QueryTree () <0x41689000 + 0x0003f> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Evaluate (System.Xml.XPath.XPathExpression expr, System.Xml.XPath.XPathNodeIterator context) <0x41688e20 + 0x0007b> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Evaluate (System.Xml.XPath.XPathExpression expr) <0x41688df0 + 0x0001a> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Select (System.Xml.XPath.XPathExpression expr) <0x41688d70 + 0x0001b> in <filename unknown>:0 
  at System.Xml.XPath.XPathNavigator.Select (System.String xpath) <0x41684000 + 0x00026> in <filename unknown>:0 
  at System.Xml.XmlNode.SelectNodes (System.String xpath) <0x416839a0 + 0x00038> in <filename unknown>:0 
  at System.Xml.XmlNode.SelectSingleNode (System.String xpath) <0x41683950 + 0x00017> in <filename unknown>:0 

I guess I need some escaping cus of the colon. But how do I do this?

MOR_SNOW
  • 787
  • 1
  • 5
  • 16
  • Sorry, this is not the real xml. For security reasons, I made this up, it looks very much like the real one. The issue is not that it's not well-formed, if it was, I would not be able to select the other attributes either. The issue lies in selecting this kind of attribute diffgr:hasChanges='modified (cus of the colon I think) – MOR_SNOW Feb 05 '18 at 14:30

1 Answers1

1

As said in the error message

Namespace Manager or XsltContext needed.

You need to set a namespace for diffgr. Otherwise the expression for the attribute @diffgr:hasChanges will not match.

In XSLT you'd add the namespace to the root element

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:diffgr='urn:schemas-microsoft-com:xml-diffgram-v1'>

In C# with XmlReader you can add a namespace like this:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(reader.NameTable);
nsmgr.AddNamespace("diffgr", "urn:schemas-microsoft-com:xml-diffgram-v1");    
XElement node = root.XPathSelectElement("/*/Data/*/@diffgr:hasChanges", nsmgr);

If this doesn't help, try this SO answer: Namespace Manager or XsltContext needed.

zx485
  • 28,498
  • 28
  • 50
  • 59
  • Another way, easier and better in my case, I found out, that I can do this: SelectSingleNode("/*/Data/*/@*[name()='diffgr:hasChanges']"); By using name(), xpath won't look at the namespace, in this case. – MOR_SNOW Feb 06 '18 at 09:37