I'm trying to query out some information from a heavily namespaced XML document and am having some trouble finding attributes that are also namespaced.

The XML looks like:

<?xml version="1.0" encoding="utf-8" ?>
<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:skos="http://www.w3.org/2004/02/skos/core#"
    xmlns:geo="http://www.geonames.org/ontology#"
    xmlns:dc="http://purl.org/dc/terms/"
    xmlns:foaf="http://xmlns.com/foaf/0.1/"
    xmlns:void="http://rdfs.org/ns/void#">

    <geo:Country rdf:about="http://ontologi.es/place/AD" skos:notation="AD" rdfs:label="Andorra" />
    <geo:Country rdf:about="http://ontologi.es/place/AE" skos:notation="AE" rdfs:label="United Arab Emirates" />
    <geo:Country rdf:about="http://ontologi.es/place/AF" skos:notation="AF" rdfs:label="Afghanistan" />
    <geo:Country rdf:about="http://ontologi.es/place/AG" skos:notation="AG" rdfs:label="Antigua &amp; Barbuda" />
    <geo:Country rdf:about="http://ontologi.es/place/AI" skos:notation="AI" rdfs:label="Anguilla" />
    <geo:Country rdf:about="http://ontologi.es/place/AL" skos:notation="AL" rdfs:label="Albania" /> 
    ...

</rdf:RDF>

My goal is to create a list of objects that have a country code and a country name. Here's what works for me now:

XmlReader reader = XmlReader.Create(@"path/to/xml.xml");
XDocument root = XDocument.Load(reader);
XmlNameTable nameTable = reader.NameTable;

XmlNamespaceManager nsManager = new XmlNamespaceManager(nameTable);
nsManager.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
nsManager.AddNamespace("rdfs", "http://www.w3.org/2000/01/rdf-schema#");
nsManager.AddNamespace("skos", "http://www.w3.org/2004/02/skos/core#");
nsManager.AddNamespace("geo", "http://www.geonames.org/ontology#");

var geoCountries = 
    from country in root.XPathSelectElements("./rdf:RDF/geo:Country", nsManager)
    select new {
        CountryCode = country.Attributes("{http://www.w3.org/2004/02/skos/core#}notation").First().Value,
        CountryName = country.Attributes("{http://www.w3.org/2000/01/rdf-schema#}label").First().Value
    };

This works fine, but I'd like to find the attributes using the namespace aliases, not the namespace URI (just because), or at least be able to lookup the URI using the alias. To try the latter idea, I eventually figured out I could do this:

country.Attributes(nsManager.LookupNamespace("skos") + "notation").First().Value

But I get an XmlException: The ':' character, hexadecimal value 0x3A, cannot be included in a name.

So then I tried:

country.Attributes("{" + nsManager.LookupNamespace("skos") + "}notation").First().Value

And then it works, but just seems like there could or should be an easier way, or rather, the {namespace}attribute syntax seems silly to me, like something that might be abstracted away in the framework.

  • So with all that, are there any shortcuts or easier ways to look up namespaced attributes?

I'd appreciate any feedback. Thanks!

share|improve this question
feedback

1 Answer

up vote 2 down vote accepted

using Linq to xml

XNamespace skos = XNamespace.Get("http://www.w3.org/2004/02/skos/core#");
XNamespace geo = XNamespace.Get("http://www.geonames.org/ontology#");
XNamespace rdfs = XNamespace.Get("http://www.w3.org/2000/01/rdf-schema#");

XDocument rdf = XDocument.Load(new StringReader(xmlstr));
foreach(var country in rdf.Descendants(geo + "Country"))
{
    Console.WriteLine(
        country.Attribute(skos + "notation").Value + " "  + 
        country.Attribute(rdfs + "label").Value );
}
share|improve this answer
So doing it a little more LINQy is pretty slick. Thanks for the example. – Cory Feb 17 '12 at 22:51
feedback

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.