Marcelo
Marcelo

Reputation: 3391

Getting an XML node using LINQ

Somehow, using linq I can't test it with this CUF field in the beginning:

<NFe>
    <infNFe versao="1.0" Id="NFe0000000000">
        <ide>
             <cUF>35</cUF>
             <!--...-->
        </ide>
    </infNFe>
</NFe>

With the following code:

XDocument document = XDocument.Load(@"c:\nota.xml");
            var query = from NFe in document.Descendants("NFe")
                        select new
                        {
                            cuf = NFe.Element("infNFe").Element("ide").Element("cUF").Value
                        };

The whole XML loads into document (checked) but NFe.cuf gives me nothing. I guess the parameters inside the nodes are messing it up..

How do I get this "cuf" with linq?
What if I wanted the Id parameter in infNFe ?

--[EDIT]--

I had forgotten to give the "silly url in the beginning", what happens is that it is the NAMESPACE, (the non-displaying of the namespace of the xml in Firefox contributed)

Now this works:

        XNamespace ns = "http://www.portalfiscal.inf.br/nfe";
        XElement root = XElement.Load(@"c:\nota.xml");

        textBox1.Text = root.Element(ns + "infNFe").Element(ns + "ide").Element(ns + "cUF").Value;

Is there a way to set the namespace somewhere, and not needing to put it in every single field call ?

Upvotes: 2

Views: 1917

Answers (6)

Kirk Broadhurst
Kirk Broadhurst

Reputation: 28718

edit: Use an XElement, it's much easier.

Now you're using namespaces, so you need to specify those too with XNamespace

If you aren't sure where it's breaking, simply split your query into multiple lines like the below so that you can step through and determine where the error is occurring.

XNamespace ns = "http://www.somewebsite.com";
XElement root = XElement.Load(@"c:\nota.xml");
var infNFe = root.Element(ns + "infNFe");
var ide = infNFe.Element(ns + "ide");
var cUF = ide.Element(ns + "cUF");
var value = cUF.Value;

To clarify the namespace issue, if you have XML like

<a xmlns="namespace">
    <b>123</b>
</a>

then a.Element("b") doesn't exist. You need to interrogate the element b with namespace namespace. Just like namespaces anywhere else in C# - they are something like dimensions. You are looking in the right path but in the wrong dimension.

Upvotes: 0

Klaus Byskov Pedersen
Klaus Byskov Pedersen

Reputation: 120937

Actually, when running your code I don't see any problem. I've done the follwing:

XDocument document = XDocument.Load(@"c:\temp\nota.xml");
var query = from NFe in document.Descendants("NFe")
            select new
            {
                cuf = NFe.Element("infNFe").Element("ide").Element("cUF").Value,
                infId = NFe.Element("infNFe").Attribute("Id").Value
            };

foreach(var v in query)
    Console.WriteLine(v.cuf + " " + v.infId);

Given the following xml:

<NFe> 
<infNFe versao="1.0" Id="NFe0000000000"> 
<ide> 
<cUF>35</cUF> 
</ide>
</infNFe>
</NFe> 

It outputs:

35 NFe0000000000

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038800

You could use XPath:

using System;
using System.Xml.Linq;
using System.Xml.XPath;

class Program
{
    static void Main(string[] args)
    {
        var doc = XDocument.Load(@"c:\nota.xml");
        var cuf = doc.XPathSelectElement("//cUF");
        if (cuf != null)
        {
            Console.WriteLine(cuf.Value);
        }

        var infNFe = doc.XPathSelectElement("//infNFe");
        if (infNFe != null)
        {
            var id = infNFe.Attribute("Id");
            if (id != null) 
            {
                Console.WriteLine(id.Value);
            }
        }

    }
}

given this XML:

<?xml version="1.0"?>
<NFe>
  <infNFe versao="1.0" Id="NFe0000000000">
    <ide>
      <cUF>35</cUF>
    </ide>
  </infNFe>
</NFe>

Upvotes: 0

undertakeror
undertakeror

Reputation: 1022

try query.SingleOrDefault();

Upvotes: 0

Andy Shellam
Andy Shellam

Reputation: 15535

You don't really need that full LINQ query - a single one-liner will do:

string cuf = document.Root.Element("infNFe").Element("ide").Element("cUF").Value;
// cuf = 35

The same for the ID:

string id = document.Root.Element("infNFe").Attribute("Id").Value;
// id = NFe0000000000

Upvotes: 3

You're looking at document.Descendants, which is all the elements inside the root.

document.Descendants in your case would contain infNFe, ide, cUF ... which is why you cannot find the root in the collection.

Try using document.Root instead.

Upvotes: 1

Related Questions