7

I have the following xml as string:

<cfdi:Comprobante version="3.0"
                  xsi:schemaLocation="http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv3.xsd"
                  serie="A"
                  folio="6"
                  fecha="2011-07-22T13:51:42"
                  formaDePago="Pago en una sola exhibición"
                  sello="XlSJYAxauwYbI"
                  noCertificado="00001000000101242210"
                  certificado="YtEQOHw02OGx6E="
                  condicionesDePago="Paguese a mas tardar el 21/08/2011."
                  subTotal="123"
                  Moneda="MXN"
                  total="123"
                  tipoDeComprobante="ingreso">
  <cfdi:Complemento>
    <tfd:TimbreFiscalDigital FechaTimbrado="2011-07-22T13:51:47"
                             UUID="41C8A54F-4956-1BAD-F2CB-48E8343918FD"
                             noCertificadoSAT="00001000000102616613"
                             selloCFD="wrwerewe"
                             version="1.0"
                             xsi:schemaLocation="http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/timbrefiscaldigital/TimbreFiscalDigital.xsd"/>
  </cfdi:Complemento>
</cfdi:Comprobante>

I want to read the attribute UUID inside the node tfd:TimbreFiscalDigital so I was wondering how to do this using c#, this might be silly but please understand I'm new in c#.

Note: This xml is inside a string, not in a file (our provider's webservice returns the xml as string, is not our fault)

Note2: I can use Linq, or any other library, that's not a prob

Thanks!!

2
  • Would be nice to format the XML over multiple lines for readability Commented Oct 6, 2011 at 0:37
  • 2
    It's not well-formed XML. Specifically, there is no definition for the xml namespace prefixes xsi, tfd, or cfdi. If you want to parse the XML with any XML library in .NET, you will first need to get it so that it is well-formed. That may mean a manual fixup, if they are not sending you proper XML. Commented Oct 6, 2011 at 0:58

3 Answers 3

2

I wrapped this in a root node declaring the namespaces. I'm also using XPath to query for the node.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml;

class Program
{
    static void Main(string[] args)
    {

        var doc = @"
<Root xmlns:xsi='http://someuri' xmlns:cfdi='http://someuri2' xmlns:tfd='http://someuri3'>
<cfdi:Comprobante version='3.0'
                  xsi:schemaLocation='http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv3.xsd'
                  serie='A'
                  folio='6'
                  fecha='2011-07-22T13:51:42'
                  formaDePago='Pago en una sola exhibición'
                  sello='XlSJYAxauwYbI'
                  noCertificado='00001000000101242210'
                  certificado='YtEQOHw02OGx6E='
                  condicionesDePago='Paguese a mas tardar el 21/08/2011.'
                  subTotal='123'
                  Moneda='MXN'
                  total='123'
                  tipoDeComprobante='ingreso'>
  <cfdi:Complemento>
    <tfd:TimbreFiscalDigital FechaTimbrado='2011-07-22T13:51:47'
                             UUID='41C8A54F-4956-1BAD-F2CB-48E8343918FD'
                             noCertificadoSAT='00001000000102616613'
                             selloCFD='wrwerewe'
                             version='1.0'
                             xsi:schemaLocation='http://www.sat.gob.mx/TimbreFiscalDigital http://www.sat.gob.mx/sitio_internet/timbrefiscaldigital/TimbreFiscalDigital.xsd'/>
  </cfdi:Complemento>
</cfdi:Comprobante>
</Root>";

        var uuid = XDocument.Parse(doc)
            var uuid = XDocument.Parse(doc)
            .XPathSelectElement("//*[local-name() = 'TimbreFiscalDigital']")
            .Attribute("UUID").Value;

        // Work with uuid

        Console.Read();
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

The wrapping in the additional root element is a good idea. But your xpath won't work without using the xml namespaces.
that;s right it marks an error: 'System.Xml.Linq.XDocument' does not contain a definition for 'XPathSelectElement' and no extension method 'XPathSelectElement' accepting a first argument of type 'System.Xml.Linq.XDocument' could be found (are you missing a using directive or an assembly reference?)
@franko_camron - If you noticed in my code - you need to have using System.Xml.XPath; in your code. This code works perfectly fine, otherwise. The accepted answer won't work because of the missing namespace.
1

Because you have namespace prefixes, you'll have to use XNamespace instances to help you reference the elements.

// We use these to establish our namespace prefixes
XNamespace cfdi = @"http://www.sat.gob.mx/cfd/3";
XNamespace tfd = @"http://www.sat.gob.mx/TimbreFiscalDigital";

var xdoc = XDocument.Parse(xml);

// Walk down the XML tree to tfd:TimbreFiscalDigital
var elt = xdoc.Element(cfdi + "Comprobante")
              .Element(cfdi + "Complemento")
              .Element(tfd + "TimbreFiscalDigital");
// Alternately
// var elt = xdoc.Descendants(tfd + "TimbreFiscalDigital")
//               .First();

var uuid = (string)elt.Attribute("UUID");

// You can convert attributes and element values to lots of built-in types
// See the Explicit Conversions for XAttribute and XElement on MSDN
var date = (DateTime)elt.Attribute("FechaTimbrado");

Further reading:

5 Comments

This won't compile. First two lines should be XNamespace.Get("http....
Thanks, that'll teach me to type it on my Macbook. I've switched to the preferred form.
I think it will compile now, but it won't run, because the xml as included in the original question, is not well-formed. It uses namespace prefixes that are not defined. Therefore your XDocument.Parse() will throw.
@Cheeso: I read your comment after I fixed my issue. I didn't catch the example fragment was the complete XML. Well time to add some bolt on hackery.
After checking all the solutions turns out this was the only one that worked for me because of the namespaces. Maybe it's not the neatest solution but it works! thanks man
1

I find linq's XDocument and related classes to be particularly simple and straightforward to use:

string uuid = XDocument.Parse(xmlString)
    .Descendants("TimbreFiscalDigital")
    .Attributes("UUID")
    .First()
    .Value;

1 Comment

Nice and short, except you need to consider the xml namespaces.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.