Google Earth 中 KML 文件都采用了下面的属性定义
<kmlxmlns="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 与当前元素的标签名相同,这样在使用 XPath 语法选择子元素等操作时一直返回为NULL
不知道 Google 最初为社么这样设计的,但在 C# 语言中使用 XmlDocument 的 读取时无法正确读出来。
测试的KML文件如下 :
<?xmlversion="1.0"encoding="UTF-8"?> <kmlxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:kml="http://www.opengis.net/kml/2.2"> <Document> <Placemark> <name>中牟站</name> <styleUrl>#m_ylw-pushpin16</styleUrl> <Polygon> <tessellate>1</tessellate> <outerBoundaryIs> <LinearRing> <coordinates> 114.0181288105562,34.70732579930824,0 114.0182028197397,34.70717842472297,0 114.0191556334107,34.70729121976968,0 </coordinates> </LinearRing> </outerBoundaryIs> </Polygon> </Placemark> </Document> </kml>
然后使用 C# 进行选取元素
XmlDocumentxml=newXmlDocument(); xml.Load(@"D:\Documents\VisualStudio2013\Projects\WindowsFormsApplication1\WindowsFormsApplication1\中牟站.kml"); //XPath XmlNodeListnodes=xml.SelectNodes("/kml/Document/Placemark");
调试下的结果 :
在调试的时候发现使用 FirstChild 和 LastChild 可以正确地访问 根节点 <kml>,但是进入子节点后就不能识别了,表示好郁闷
第一次碰到这个问题的时候不想仔细去想就直接干kml节点了,今天再碰到就表示不能什么都归结于人品问题吧。认真一下就发现这个 xmlns:kml 定义竟然跟节点名称一样,是XMl的标准不允许这样的语法,还是Google的疏忽?
现在有一个包含复杂元素的类需要序列化
[Serializable] publicclassCompany { [XmlElement] publicintCount{get;set;} [XmlElement] publicList<Person>PersonList{get;set;} [XmlElement] publicPersonLeader{get;set;} }
可以是序列化后发现有一个小问题
<?xmlversion="1.0"?> <Companyxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Count>5</Count> <PersonList> <Name>MISSDD</Name> <Age>20</Age> <Sex>Female</Sex> <Direction>Left</Direction> </PersonList> <PersonList> <Name>MR.DD</Name> <Age>19</Age> <Sex>Male</Sex> <Direction>Right</Direction> </PersonList> <Leader> <Name>MRSDDL</Name> <Age>23</Age> <Sex>Unknow</Sex> <Direction>Right</Direction> </Leader> </Company>
第二个属性 PersonList 没有正确地嵌套层次关系,它的子元素直接当作类的属性输出了,是什么原因导致的?仔细实验了一下,原来是属性定义时使用了错误的XML特性声明。
XmlElementAttribute
指示公共字段或属性在 System.Xml.Serialization.XmlSerializer 序列化或反序列化包含它们的对象时表示 XML元素。
XmlArrayAttribute
指定 System.Xml.Serialization.XmlSerializer 必须将特定的类成员序列化为 XML 元素的数组。
XmlArrayItem
表示指定 System.Xml.Serialization.XmlSerializer 可以放置在序列化数组中的派生类型的特性。
XmlAttribute
指定 System.Xml.Serialization.XmlSerializer 必须将类成员序列化为 XML 特性。
正是由于对这几个特性声明对应的含义不了解导致的错误。本来我们的集合元素 PersonList 应该是 XmlArray 类型的,但是由于代码中指定成了元素,所以就少了一层嵌套。因为没搞明白多加的声明反而画蛇添足了,所以只要去掉或者换成正确的特性声明就会回归正常的输出。
<?xmlversion="1.0"?> <Companyxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Count>5</Count> <PersonList> <Person> <Name>MISSDD</Name> <Age>20</Age> <Sex>Female</Sex> <Direction>Left</Direction> </Person> <Person> <Name>MR.DD</Name> <Age>19</Age> <Sex>Male</Sex> <Direction>Right</Direction> </Person> </PersonList> <Leader> <Name>MRSDDL</Name> <Age>23</Age> <Sex>Unknow</Sex> <Direction>Right</Direction> </Leader> </Company>