我正在使用Linq to XML解析XML文本。返回的XDocument将所有这个命名空间添加到我的每个节点,并且无法找到后代,或者至少,我对“Placemark”的搜索不起作用,很可能是因为kml:Placemark不适合搜索。
当我在单元测试中使用基本XML文件测试它时,它工作正常。我猜测XML声明部分没有所有名称空间。
如果不添加所有命名空间,我如何解析XML文本?
解析:
XDocument document = XDocument.Parse(text);
var polygonNodes = document.Descendants("Polygon"); // yields no nodes, even though there are descendants with this.
原始文件
<?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>
解析XDocument(根节点)
<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>
答案 0 :(得分:2)
我认为您遇到了LINQ to XML数据模型的缺点,它不会在其模型中存储元素或属性名称的前缀部分,而只是存储名称空间声明属性(例如xmlns="..."
和xmlns:pf="..."
)然后在序列化对象树以进行标记时,它会尝试推断元素和属性的前缀。在您的示例中,命名空间http://www.opengis.net/kml/2.2
定义了两次,一次是xmlns="http://www.opengis.net/kml/2.2"
的默认命名空间,一次是前缀kml
(xmlns:kml="http://www.opengis.net/kml/2.2"
)。在这种情况下,推断元素名称前缀的尝试被破坏,看起来实现将最后一个声明考虑为
string xml = @"<foo xmlns=""http://example.com/ns1"" xmlns:pf=""http://example.com/ns1""/>";
XDocument doc = XDocument.Parse(xml);
doc.Save(Console.Out);
输出
<pf:foo xmlns="http://example.com/ns1" xmlns:pf="http://example.com/ns1" />
,而
string xml = @"<foo xmlns:pf=""http://example.com/ns1"" xmlns=""http://example.com/ns1""/>";
XDocument doc = XDocument.Parse(xml);
doc.Save(Console.Out);
输出
<foo xmlns:pf="http://example.com/ns1" xmlns="http://example.com/ns1" />
因此,除非在创建输入时控制命名空间声明的顺序,否则对于同一命名空间的两个命名空间声明的输入XML可能不会使用XDocument或XElement进行往返。
尽管如此,只要元素位于命名空间中,LINQ to XML使用Descendants
或Elements
或Element
方法访问它们的正确方法是使用连接一个XNamespace
string
来构建XName
例如
XNamespace ns = doc.Root.Namespace;
IEnumerable<XElement> fooElements = doc.Descendants(ns + "foo");
答案 1 :(得分:0)
使用此
XNamespace kmlNS = "http://www.opengis.net/kml/2.2";
XDocument document = XDocument.Parse(text);
var polygonNodes = document.Descendants(kmlNS+"Polygon");