views:

291

answers:

1

I have the following XPATH line:

//det[@nItem="1"]/prod/cProd

That successfully selects the desired node using XPath Visualizer, where it identifies automatically the namespace, and you define in which namespace you want to select.

When I specify the namespace in C# with the following XPATH code:

"http://www.portalfiscal.inf.br/nfe//det[@nItem=\"1\"]/prod/cProd"

it gives me an XPathException:

An unhandled exception of type 'System.Xml.XPath.XPathException' occurred in System.Xml.dll Additional information: 'http://www.portalfiscal.inf.br/nfe//det[@nItem="1"]/prod/cProd' has an invalid qualified name.

(as you can see, it's not any escape character or anything, since it gives me what i've tried to reach in the exception)

How do I properly select this node providing that I know the namespace with XPath ?

--[EDIT]-- The complete line where I try to read the node:

doc.XPathSelectElement("http://www.portalfiscal.inf.br/nfe//det[@nItem=\"1\"]/prod/cProd").Value;

And the XML with unnecessary things cut out:

<?xml version="1.0" encoding="utf-8"?>
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="1.10">
<idLote>1</idLote>
<NFe>
<infNFe versao="1.10" Id="NFe31100118583682000178550010000077778397333128">
<det nItem="1">
<prod>
<cProd>111</cProd>
</prod>
</det>
</infNFe>
</NFe>
</enviNFe>

(The unnecessary things cut out should not be a problem, since XPath Visualizer brought me the node with no problems at all)

+2  A: 

Since you're not showing us neither the XML document, nor the C# code you have, I can only guess what you're doing....

OK, seems you're using Linq-to-XML, so then use this code snippet here:

// Create and load XML reader
XmlReader reader = XmlReader.Create(new FileStream(@"D.\test.xml", FileAccess.Read));

// get the root element    
XElement root = XElement.Load(reader);


// create instance of XML namespace manager
XmlNamespaceManager nsmgr = new XmlNamespaceManager(reader.NameTable);

// add your namespace to the manager and give it a prefix
nsmgr.AddNamespace("ns", "http://www.portalfiscal.inf.br/nfe");

XElement node = root.XPathSelectElement("//ns:det[@nItem="1"]/ns:prod/ns:cProd", nsmgr);
.......

Something along those lines. You basically have to create a XML namespace of some sort, give it a prefix, and then use that prefix in your XPath expression - not the whole namespace - just the prefix.

marc_s
If you are not worried about performance you can select nodes by ignoring the namespace "//*[local-name()='det' and @*[local-name()='nItem']=1]/*[local-name()='prod']/*[local-name()='cProd']"
Greg
I've seen namespaces being used in the start of the xpath (like my non-working example) is there a way to put it IN the xpath syntax ?
MarceloRamires
@MarceloRamires: not to my knowledge, no - as far as I know, you have to create a prefix for the XML namespace and use it that way. I've never seen the full namespace used directly in the XPath
marc_s
There are other problems with using `local-name()` besides performance. The most significant one is simply what it's doing: ignoring namespaces. Whenever you ignore namespaces, you run the risk of selecting nodes that are in a different namespace but happen to have the same local name as what you're looking for. That's bad.
Robert Rossney