如何为XML属性添加命名空间前缀(C# XmlSerializer场景)
如何让XML序列化时属性带上指定命名空间前缀?
你当前的代码中,虽然给Name属性标记了正确的命名空间,但XmlSerializer默认会省略与父元素同命名空间的属性前缀(符合XML规范,属性可继承父元素的命名空间)。要强制给属性加上epd:前缀,不能直接在属性名中添加前缀(这会违反XML命名规则导致序列化失败),可以通过以下两种方式实现:
方案一:实现IXmlSerializable接口自定义序列化
通过手动控制XML的写入逻辑,完全掌控元素和属性的前缀输出。修改后的scenario类代码如下:
[System.SerializableAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.testingmcafeesites.com/testcat_bl.html")] [System.Xml.Serialization.XmlRootAttribute("scenario", Namespace = "http://www.testingmcafeesites.com/testcat_bl.html", IsNullable = false)] public partial class scenario : IXmlSerializable { private string nameField; private description descriptionField; public string Name { get { return this.nameField; } set { this.nameField = value; } } public description description { get { return this.descriptionField; } set { this.descriptionField = value; } } public System.Xml.Schema.XmlSchema GetSchema() { return null; } public void ReadXml(System.Xml.XmlReader reader) { // 按需实现反序列化逻辑 Name = reader.GetAttribute("name", "http://www.testingmcafeesites.com/testcat_bl.html"); reader.ReadStartElement(); if (reader.Name == "description" && reader.NamespaceURI == "http://www.testingmcafeesites.com/testcat_bl.html") { description = new description(); description.ReadXml(reader); } reader.ReadEndElement(); } public void WriteXml(System.Xml.XmlWriter writer) { // 手动写入带epd前缀的name属性 writer.WriteAttributeString("epd", "name", "http://www.testingmcafeesites.com/testcat_bl.html", Name); // 写入description元素(按需调整) if (description != null) { writer.WriteStartElement("epd", "description", "http://www.testingmcafeesites.com/testcat_bl.html"); description.WriteXml(writer); writer.WriteEndElement(); } } [System.Xml.Serialization.XmlNamespaceDeclarations] public System.Xml.Serialization.XmlSerializerNamespaces XmlNamespaces { get { var namespaces = new System.Xml.Serialization.XmlSerializerNamespaces(); namespaces.Add("epd", "http://www.testingmcafeesites.com/testcat_bl.html"); return namespaces; } set { } } }
注意:description类也需要实现IXmlSerializable接口,或者根据其结构调整写入逻辑。
方案二:序列化时手动控制XmlWriter输出
如果不想修改原类结构,可以在序列化过程中直接使用XmlWriter手动构建XML内容:
var scenarioObj = new scenario { Name = "Reuse" }; var namespaces = new XmlSerializerNamespaces(); namespaces.Add("epd", "http://www.testingmcafeesites.com/testcat_bl.html"); using (var stringWriter = new StringWriter()) using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { OmitXmlDeclaration = true })) { // 写入根元素 xmlWriter.WriteStartElement("epd", "scenario", "http://www.testingmcafeesites.com/testcat_bl.html"); // 手动写入带epd前缀的name属性 xmlWriter.WriteAttributeString("epd", "name", "http://www.testingmcafeesites.com/testcat_bl.html", scenarioObj.Name); // 按需写入description元素 if (scenarioObj.description != null) { var descSerializer = new XmlSerializer(typeof(description)); descSerializer.Serialize(xmlWriter, scenarioObj.description, namespaces); } xmlWriter.WriteEndElement(); xmlWriter.Flush(); var serializedXml = stringWriter.ToString(); // serializedXml即为目标格式的XML字符串 }
为什么直接加前缀会失败?
XML属性的本地名称不允许包含冒号(冒号是前缀与本地名称的分隔符),直接在XmlAttributeAttribute中指定"epd:name"会违反XML命名规范,导致序列化器抛出异常。
内容的提问来源于stack exchange,提问作者Maksym Kuzmych
相关产品推荐
相关产品推荐

