问题描述
我正在使用 XmlSerializer 创建一个表示 XML 文件的对象,现在我想将 schemalocation 添加到我的 xml 文件的根元素中.我可以添加如下命名空间
I am using XmlSerializer to create an object representing an XML file and now i want to add a schemalocation to the rootelement of my xml file.I can add namespaces like the following
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
System.IO.FileStream fs = new FileStream(@"C: est.xml", FileMode.Create);
TextWriter writer = new StreamWriter(fs, new UTF8Encoding());
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("xy","http://www.w3.org/2005/08/addressing");
ns.Add("xlink","http://www.w3.org/1999/xlink");
serializer.Serialize(writer, myObject, ns);
但是如何在我的 c# 代码中将 xsi:schemalocation
属性添加到我的根元素.命名空间是用一个简单的 ns.Add()
添加的.我想避免弄乱 xsd.exe 生成的 c# 类.还是我必须手动编辑生成的 c# 类并向我的 xml 的根元素添加一些属性?
But how do i add a xsi:schemalocation
attribute to my root element within my c# code. Namespace was added with a simple ns.Add()
. I would like to avoid messing around with the xsd.exe generated c# class.Or do i have to edit manually the generated c# class and add some attribute to the root element of my xml?
我已经看到了需要手动编辑 c# 的示例,但必须有一种方法可以在代码中进行!如果我们能够向根元素添加命名空间,为什么不能添加模式位置?
I have seen examples where i need to edit my c# manually, but there must be a way to do it in code!! If we are able to add namespaces to our root element, why shouldn't it be possible to add schemalocations?
推荐答案
让我们假设以下 XSD:
Let's assume the following XSD:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="elementB">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FirstName" type="xsd:string"/>
<xsd:element name="LastName" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
至少有两种方法可以做到这一点.第一个依赖于继承以及如何使用序列化器注释.
There are two ways at least to do it. The first one relies on inheritance and how you can play with the serializer annotations.
xsd.exe 生成这个:
xsd.exe generates this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18034
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=4.0.30319.1.
//
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://tempuri.org/XMLSchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://tempuri.org/XMLSchema.xsd", IsNullable=false)]
public partial class elementB {
private string firstNameField;
private string lastNameField;
/// <remarks/>
public string FirstName {
get {
return this.firstNameField;
}
set {
this.firstNameField = value;
}
}
/// <remarks/>
public string LastName {
get {
return this.lastNameField;
}
set {
this.lastNameField = value;
}
}
}
要注入" xsi:schemaLocation
添加一个新类 elementA : elementB
;注意:
To "inject" the xsi:schemaLocation
add a new class, elementA : elementB
; notice:
- System.Xml.Serialization.XmlRootAttribute 设置
schemaLocation
属性设置.
- System.Xml.Serialization.XmlRootAttribute setup
schemaLocation
property setup.
测试程序:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
elementB b = new elementB();
b.FirstName = "P";
b.LastName = "G";
XmlSerializer ser = new XmlSerializer(typeof(elementB));
StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
{
ser.Serialize(writer, b);
}
Console.WriteLine(sb.ToString());
elementA a = new elementA();
a.FirstName = "P";
a.LastName = "G";
a.schemaLocation = "http://tempuri.org/XMLSchema.xsd me";
ser = new XmlSerializer(typeof(elementA));
sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
{
ser.Serialize(writer, a);
}
Console.WriteLine(sb.ToString());
}
}
}
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://tempuri.org/XMLSchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://tempuri.org/XMLSchema.xsd", ElementName = "elementB", IsNullable = false)]
public partial class elementA : elementB
{
private string torefField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute(Form = System.Xml.Schema.XmlSchemaForm.Qualified, Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string schemaLocation
{
get
{
return this.torefField;
}
set
{
this.torefField = value;
}
}
}
产生预期的结果:
<?xml version="1.0" encoding="utf-16"?>
<elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/XMLSchema.xsd">
<FirstName>P</FirstName>
<LastName>G</LastName>
</elementB>
<?xml version="1.0" encoding="utf-16"?>
<elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd me" xmlns="http://tempuri.org/XMLSchema.xsd">
<FirstName>Petru</FirstName>
<LastName>Gardea</LastName>
</elementB>
第二种方式依赖于自定义编写器,它将在任何你想要的地方注入你想要的东西(假设有适当的逻辑).
The second way relies on a custom writer that will inject what you want, wherever you want it (assuming the appropriate logic).
您实现了一个自定义 XmlWriter:
You implement a custom XmlWriter:
class MyXmlWriter : XmlWriter
{
XmlWriter _writer;
bool _docElement = true;
public string SchemaLocation { get; set; }
public string NoNamespaceSchemaLocation { get; set; }
public MyXmlWriter(XmlWriter writer)
{
_writer = writer;
}
(other methods omitted)
public override void WriteStartElement(string prefix, string localName, string ns)
{
_writer.WriteStartElement(prefix, localName, ns);
if (_docElement)
{
if (!string.IsNullOrEmpty(SchemaLocation))
{
_writer.WriteAttributeString("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance", SchemaLocation);
}
if (!string.IsNullOrEmpty(NoNamespaceSchemaLocation))
{
_writer.WriteAttributeString("xsi", "noNamesapceSchemaLocation", "http://www.w3.org/2001/XMLSchema-instance", NoNamespaceSchemaLocation);
}
_docElement = false;
}
}
(other methods omitted)
}
修改后的测试程序:
static void Main(string[] args)
{
elementB b = new elementB();
b.FirstName = "P";
b.LastName = "G";
XmlSerializer ser = new XmlSerializer(typeof(elementB));
StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
{
ser.Serialize(writer, b);
}
Console.WriteLine(sb.ToString());
sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
{
MyXmlWriter newWriter = new MyXmlWriter(writer) { SchemaLocation = "http://tempuri.org/XMLSchema.xsd me" };
ser.Serialize(newWriter, b);
}
Console.WriteLine(sb.ToString());
}
结果是一样的……
<?xml version="1.0" encoding="utf-16"?>
<elementB xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/XMLSchema.xsd">
<FirstName>P</FirstName>
<LastName>G</LastName>
</elementB>
<?xml version="1.0" encoding="utf-16"?>
<elementB xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd me" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<FirstName>P</FirstName>
<LastName>G</LastName>
</elementB>
这篇关于如何将 xsi schemalocation 添加到根 c# object XmlSerializer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!