An efficient way to parse XML

I find it puzzling to figure out the best way to parse some XML. They seem to have so many possible paths and none of them clicked with me.

My current attempt looks something like this:

XElement xelement = XElement.Parse(xmlText);
var name = xelement.Element("Employee").Attribute("name").Value;

      

So it works. But it throws an exception if the "Employee" or "Name" element is missing. I don't want to throw an exception.

While researching some examples available on the internet , I see code like this:

XElement xelement = XElement.Load("..\\..\\Employees.xml");
IEnumerable<XElement> employees = xelement.Elements();
Console.WriteLine("List of all Employee Names :");
foreach (var employee in employees)
{
    Console.WriteLine(employee.Element("Name").Value);
}

      

It seems to be suffering from the same problem. If Name does not exist, Element()

returns null

and displays an error calling the property Value

.

I need a few blocks like the first code snippet above. Is there an easy way to make it work and not throw an exception if some data is missing?

+3


source to share


5 answers


You can use a combination of explicit string conversion from XAttribute

to string

(which will return null if the operand is null) and the method FirstOrDefault

:

var name = xelement.Elements("Employee")
                   .Select(x => (string) x.Attribute("name"))
                   .FirstOrDefault();

      



It will be null if either there is no such element (because the sequence will be empty and FirstOrDefault()

will return null), or there will be an element with no attribute (in which case you will get a sequence with a null element that FirstOrDefault

will return).

+3


source


I often use extension methods in cases like this where they work even if the reference is null. I'm using a slightly modified version of the extension method from Anders Abel, a very good blog post since early 2012. Null Handling with Extension Methods :

public static class XElementExtension
{
    public static string GetValueOrDefault(this XAttribute attribute,
                                           string defaultValue = null)
    {
        return attribute == null ? defaultValue : attribute.Value;
    }

    public static string GetAttributeValueOrDefault(this XElement element,
                                                    string attributeName, 
                                                    string defaultValue = null)
    {
        return element == null ? defaultValue : element.Attribut(attributeName)
                                                .GetValueOrDefault(defaultValue);
    }
}

      

If you want to return "null" if the element or attribute doesn't exist:

var name = xelement.Element("Employee")
                   .GetAttributeValueOrDefault("name" );

      



If you want to return the default value if the element or attribute doesn't exist:

var name = xelement.Element("Employee")
                    .GetAttributeValueOrDefault("name","this is the default value");

      

For use in a for loop:

XElement xelement = XElement.Load("..\\..\\Employees.xml");
IEnumerable<XElement> employees = xelement.Elements();
Console.WriteLine("List of all Employee Names :");
foreach (var employee in employees)
{
    Console.WriteLine(employee.GetAttributeValueOrDefault("Name"));
}

      

+3


source


You can always use XPath:

string name = xelement.XPathEvaluate("string(Employee/@name)") as string;

      

It will be either the value of the attribute, or null

, if it doesn't exist, Employee

or @name

.

And for an iterative example:

foreach (XNode item in (IEnumerable)xelement.XPathEvaluate("Employee/Name"))
{
     Console.WriteLine(item.Value);
}

      

XPathEvaluate()

will only select valid nodes here, so you can be sure it item

will always be non-null.

+2


source


It all depends on what you want to do with the data, once you've extracted it from XML.

You should have looked at languages โ€‹โ€‹designed to handle XML like XSLT and XQuery instead of using languages โ€‹โ€‹like C #, which aren't (although Linq gives you something of a hybrid). Using C # or Java, you will always have to work hard to deal with the fact that XML is so flexible.

0


source


Use your own XmlReader . If your problem is reading large XML files instead of letting the XElement create a representation of the object, you can create something like a Java SAX parser that's just an XML stream .

Example: http://www.codeguru.com/csharp/csharp/cs_data/xml/article.php/c4221/Writing-XML-SAX-Parsers-in-C.htm

0


source







All Articles