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 & 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.
I'd appreciate any feedback. Thanks!
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 );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With