I’m parsing XML text using Linq to XML. The returned XDocument adds all this namespacing to each of my nodes, and makes finding descendants impossible, or atleast, my search for “Placemark” doesn’t work, most likely because kml:Placemark doesn’t fit the search.
When I tested this in a unit test, with a basic XML file, it worked fine. I’m guessing the XML Declaration portion didn’t have all the namespaces.
How can I parse the XML text without it adding all the namespaces?
Parsing:
XDocument document = XDocument.Parse(text);
var polygonNodes = document.Descendants("Polygon"); // yields no nodes, even though there are descendants with this.
Original File
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>poly1_philmont.kml</name>
<Style id="s_ylw-pushpin_hl">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels"/>
</IconStyle>
<LineStyle>
<color>ff0000aa</color>
</LineStyle>
<PolyStyle>
<color>33ffaa00</color>
</PolyStyle>
</Style>
... </kml>
Parsed with XDocument (root node)
<kml:kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<kml:Document>
<kml:name>poly1_philmont.kml</kml:name>
<kml:Style id="s_ylw-pushpin_hl">
<kml:IconStyle>
<kml:scale>1.3</kml:scale>
<kml:Icon>
<kml:href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</kml:href>
</kml:Icon>
<kml:hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</kml:IconStyle>
<kml:LineStyle>
<kml:color>ff0000aa</kml:color>
</kml:LineStyle>
<kml:PolyStyle>
<kml:color>33ffaa00</kml:color>
</kml:PolyStyle>
</kml:Style>
...
</kml:kml>
I think you are experiencing a shortcoming of the LINQ to XML data model, it does not store the prefix part of an element or attribute name in its model, instead it simply stores the namespace declaration attributes (e.g.
xmlns="..."andxmlns:pf="...") and then when serializing an object tree to markup it tries to infer the prefix for elements and attributes. In your sample the namespacehttp://www.opengis.net/kml/2.2is defined twice, once as the default namespace withxmlns="http://www.opengis.net/kml/2.2", once with the prefixkml(xmlns:kml="http://www.opengis.net/kml/2.2"). In that case the attempt to infer the prefix for element names is spoiled, it looks like the implementation takes the last declaration into account asoutputs
while
outputs
So unless you control the order of namespace declarations when the input is created your input XML with two namespace declarations for the same namespace might not round-trip with XDocument or XElement.
Nevertheless, as long as elements are in a namespace, the right way with LINQ to XML to access them with the
DescendantsorElementsorElementmethod is by using the concatenation of anXNamespacewith astringto construct anXNamee.g.