XML反序列化及序列化过程中的命名空间处理问题
XML反序列化与序列化的命名空间问题解决
问题梳理
- 仅使用
[XmlRoot(ElementName = "LandXML")]时,反序列化正常,但重新序列化后丢失原XML的命名空间; - 给
XmlRoot添加Namespace属性后,反序列化直接失败; - 输入XML中的
HexagonLandXML属于独立命名空间,用[XmlType]处理无效,序列化后该元素缺失正确命名空间,无法与输入XML结构一致。
解决方案
1. LandXML根元素的命名空间修正
输入XML的LandXML根元素带有默认命名空间http://www.landxml.org/schema/LandXML-1.2,之前反序列化失败是因为未正确绑定命名空间匹配规则。修改类的XmlRoot属性,同时确保序列化时保留该命名空间:
[XmlRoot(ElementName = "LandXML", Namespace = "http://www.landxml.org/schema/LandXML-1.2")] public class LandXML { // 子元素继承根元素的默认命名空间,无需额外指定 [XmlElement(ElementName = "Units")] public Units Units { get; set; } [XmlElement(ElementName = "Survey")] public Survey Survey { get; set; } // 显式指定HexagonLandXML的命名空间 [XmlElement(ElementName = "HexagonLandXML", Namespace = "http://xml.hexagon.com/schema/HeXML-1.8")] public HexagonLandXML HexagonLandXML { get; set; } // 根元素的属性必须显式定义,否则序列化会丢失 [XmlAttribute(AttributeName = "version")] public string Version { get; set; } [XmlAttribute(AttributeName = "date")] public string Date { get; set; } [XmlAttribute(AttributeName = "time")] public string Time { get; set; } [XmlAttribute(AttributeName = "readOnly")] public bool ReadOnly { get; set; } [XmlAttribute(AttributeName = "language")] public string Language { get; set; } }
2. HexagonLandXML元素的命名空间处理
HexagonLandXML属于独立命名空间,需给类指定XmlType绑定命名空间,确保内部元素继承该命名空间:
[XmlType(Namespace = "http://xml.hexagon.com/schema/HeXML-1.8")] public class HexagonLandXML { // 内部元素自动继承类的命名空间 [XmlElement(ElementName = "Codelist")] public Codelist Codelist { get; set; } [XmlElement(ElementName = "CoordinateSystem")] public CoordinateSystem CoordinateSystem { get; set; } // 元素属性需显式定义 [XmlAttribute(AttributeName = "averagingMode")] public string AveragingMode { get; set; } [XmlAttribute(AttributeName = "averagingMethod")] public string AveragingMethod { get; set; } [XmlAttribute(AttributeName = "averagingPosLimit")] public double AveragingPosLimit { get; set; } [XmlAttribute(AttributeName = "averagingHgtLimit")] public double AveragingHgtLimit { get; set; } }
3. 序列化时保留完整命名空间与Schema信息
需通过XmlSerializerNamespaces手动添加所有需要的命名空间,同时写入xsi:schemaLocation属性:
public void SerializeLandXML(LandXML landXml, string outputPath) { var serializer = new XmlSerializer(typeof(LandXML)); var namespaces = new XmlSerializerNamespaces(); // 添加默认命名空间(对应LandXML) namespaces.Add("", "http://www.landxml.org/schema/LandXML-1.2"); // 添加xsi命名空间 namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance"); var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = false }; using (var writer = XmlWriter.Create(outputPath, settings)) { // 手动写入根元素及完整schemaLocation writer.WriteStartElement("LandXML", "http://www.landxml.org/schema/LandXML-1.2"); writer.WriteAttributeString("xsi", "schemaLocation", null, "http://www.landxml.org/schema/LandXML-1.2 http://www.landxml.org/schema/LandXML-1.2/LandXML-1.2.xsd " + "http://xml.hexagon.com/schema/HeXML-1.8 http://xml.hexagon.com/schema/HeXML-1.8.xsd"); // 写入根元素的其他属性 writer.WriteAttributeString("version", landXml.Version); writer.WriteAttributeString("date", landXml.Date); writer.WriteAttributeString("time", landXml.Time); writer.WriteAttributeString("readOnly", landXml.ReadOnly.ToString().ToLower()); writer.WriteAttributeString("language", landXml.Language); // 序列化内部元素 serializer.Serialize(writer, landXml, namespaces); writer.WriteEndElement(); } }
4. 反序列化的正确实现
只要类的XmlRoot指定了正确命名空间,反序列化即可正常执行:
public LandXML DeserializeLandXML(string inputPath) { var serializer = new XmlSerializer(typeof(LandXML)); using (var reader = new StreamReader(inputPath)) { return (LandXML)serializer.Deserialize(reader); } }
序列化后的预期XML结构
<LandXML xmlns="http://www.landxml.org/schema/LandXML-1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.landxml.org/schema/LandXML-1.2 http://www.landxml.org/schema/LandXML-1.2/LandXML-1.2.xsd http://xml.hexagon.com/schema/HeXML-1.8 http://xml.hexagon.com/schema/HeXML-1.8.xsd" version="1.2" date="2018-10-23" time="21:27:08.63" readOnly="false" language="English"> <Units> ... </Units> <Survey> ... </Survey> <HexagonLandXML xmlns="http://xml.hexagon.com/schema/HeXML-1.8" averagingMode="Average" averagingMethod="Weighted" averagingPosLimit="0.010000" averagingHgtLimit="0.015000"> <CoordinateSystem name="None"> ... </CoordinateSystem> <Codelist> ... </Codelist> </HexagonLandXML> </LandXML>
内容的提问来源于stack exchange,提问作者SteveJ71
相关产品推荐
相关产品推荐

