序列化 xml 文件的一部分。想要在根上命名空间,而不是在序列化的子元素上
Serialize part of xml file. Want namespace on root, not on serialized subelements
我正在尝试制作一个看起来像这样的 Xml 文件:
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com/MySchema.xsd">
<Level1>
<Level2>
</Level2>
</Level1 >
<Level1>
<Level2>
</Level2>
</Level1 >
etc. repeats hundreds of times
</RootLevel>
我使用 xsd.exe 实用程序从我的 xml 架构定义文件生成了一些 类。它们看起来像:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://MyCompany.com/MySchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.MyCompany.com/MySchema.xsd", IsNullable = false)]
public partial class RootLevel
{
private List<Level1> level1Field;
public List<Level1> Level1Field
{
get { return this.level1Field;}
set {this.level1Field = value;}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.MyCompany.com/MySchema.xsd")]
public partial class Level1
{
private List<Level2> level2Field;
public List<Level2> Level2Field
{
get { return this.level2Field;}
set {this.level2Field = value;}
}
/* other properties on Level1 go here*/
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.MyCompany.com/MySchema.xsd")]
public partial class Level2
{
/* properties on Level2 go here*/
}
我通过使用 XmlWriter.WriteStartElement() 写出 RootLevel 元素来制作这个文件,然后我通过创建 Level1 对象并使用 XmlSerializer 序列化它们来写出文件的其余部分。
目标
我希望文件仅在 RootLevel 元素上具有命名空间。
如果你有兴趣,这是我到目前为止尝试过的:
起点
一开始,我的 RootLevel 元素没有任何命名空间。
我的 Level1 和 Level2 元素有命名空间。
第 1 步:
我尝试通过覆盖 类 Level1 和 Level2 的 XmlTypeAttributes 上的名称空间,从 Level1 和 Level2 元素中删除名称空间。
XmlTypeAttribute attribute = new XmlTypeAttribute();
attribute.Namespace = string.Empty;
XmlAttributes attributes = new XmlAttributes();
attributes.XmlType = attribute;
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Level1), attributes);
overrides.Add(typeof(Level2), attributes);
this.xmlSerializer = new XmlSerializer(typeof(Level1), overrides);
步骤 1 结果
名称空间已从 Level2 中删除,但未从 Level1 中删除。
步骤 2
添加了更多代码以尝试从 Level1 中删除命名空间。我尝试使用 XmlSerializer.Serialize() 方法的名称空间参数来使用空名称空间。注意 "level1" 是 "Level1".
类型的对象
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add("", "");
this.xmlSerializer.Serialize(this.xmlFileWriter, level1, namespaces);
步骤 2 结果
命名空间从 Level1 和 Level2 中删除。到目前为止,一切都很好!现在我需要做的就是将命名空间的东西添加到 RootLevel。
步骤 3
由于 RootLevel 未序列化,我添加了一些 XmlWriter 代码以尝试将命名空间添加到 RootLevel。
string defaultNamespace = "http://www.MyCompany.com/MySchema.xsd";
this.xmlFileWriter.WriteStartElement("RootLevel", defaultNamespace);
this.xmlFileWriter.WriteAttributeString("xmlns", "xsi", "", "http://www.w3.org/2001/XMLSchema-instance");
this.xmlFileWriter.WriteAttributeString("xmlns", "xsd", "", "http://www.w3.org/2001/XMLSchema");
步骤 3 结果
名称空间已添加到 RootLevel。耶!。
但是,现在每个 Level1 元素都有一个 xmlns="" 属性。哇!
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com/MySchema.xsd">
<Level1 xmlns="">
<Level2>
</Level2>
</Level1 >
<Level1 xmlns="">
<Level2>
</Level2>
</Level1 >
etc. repeats hundreds of times
</RootLevel>
那为什么会这样?
你没有 post 你的原始代码所以我不知道你到底哪里错了,但我能够得到你想要的 XML 如下:
提取静态助手 class XmlNamespaces
来保存命名空间字符串并将它们声明为 const
字符串。在您的问题中,您有时使用 "http://MyCompany.com/MySchema.xsd"
但有时使用 "http://www.MyCompany.com/MySchema.xsd"
。这可能只是问题中的错字,但如果您的代码不一致地使用这些将导致错误。
除了XmlTypeAttribute
之外,对classLevel1
应用XmlRootAttribute
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = XmlNamespaces.Default, IsNullable = false)]
public partial class Level1
{
// Properties
}
写入根元素时,将默认命名空间字符串传递给XmlWriter.WriteStartElement(string, string)
。
整体代码如下:
public static class XmlNamespaces
{
public const string Default = "http://MyCompany.com/MySchema.xsd";
public const string xsi = "http://www.w3.org/2001/XMLSchema-instance";
public const string xsd = "http://www.w3.org/2001/XMLSchema";
public static XmlSerializerNamespaces XmlSerializerNamespaces
{
get
{
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("", XmlNamespaces.Default);
namespaces.Add("xsi", XmlNamespaces.xsi);
namespaces.Add("xsd", XmlNamespaces.xsd);
return namespaces;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = XmlNamespaces.Default, IsNullable = false)] // Added this and used const string from XmlNamespaces class
public partial class Level1
{
private List<Level2> level2Field;
public List<Level2> Level2Field
{
get { return this.level2Field; }
set { this.level2Field = value; }
}
/* other properties on Level1 go here*/
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)] // Used const string from XmlNamespaces class
public partial class Level2
{
/* properties on Level2 go here*/
}
public static class XmlSerializationUtilities
{
public static void WriteList<TItem>(string rootName, XmlSerializerNamespaces namespaces, IEnumerable<TItem> list, TextWriter textWriter)
{
var namespaceList = namespaces.ToArray();
string defaultNamespace = null;
foreach (var ns in namespaceList)
{
if (string.IsNullOrEmpty(ns.Name))
{
defaultNamespace = ns.Namespace;
break;
}
}
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = " ";
using (var writer = XmlWriter.Create(textWriter, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement(rootName, defaultNamespace);
foreach (var ns in namespaceList)
if (!string.IsNullOrEmpty(ns.Name))
writer.WriteAttributeString("xmlns", ns.Name, null, ns.Namespace);
var serializer = new XmlSerializer(typeof(TItem));
foreach (var item in list)
{
serializer.Serialize(writer, item);
}
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
}
public static class TestClass
{
public static void Test()
{
var list = new List<Level1> { new Level1 { Level2Field = new List<Level2> { new Level2(), new Level2() } }, new Level1 { Level2Field = new List<Level2> { new Level2(), new Level2(), new Level2(), new Level2() } } };
string xml;
using (var writer = new StringWriter())
{
XmlSerializationUtilities.WriteList("RootLevel", XmlNamespaces.XmlSerializerNamespaces, list, writer);
xml = writer.ToString();
Debug.WriteLine(xml);
}
}
}
输出为
<?xml version="1.0" encoding="utf-16"?>
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://MyCompany.com/MySchema.xsd">
<Level1>
<Level2Field>
<Level2 />
<Level2 />
</Level2Field>
</Level1>
<Level1>
<Level2Field>
<Level2 />
<Level2 />
<Level2 />
<Level2 />
</Level2Field>
</Level1>
</RootLevel>
我正在尝试制作一个看起来像这样的 Xml 文件:
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com/MySchema.xsd">
<Level1>
<Level2>
</Level2>
</Level1 >
<Level1>
<Level2>
</Level2>
</Level1 >
etc. repeats hundreds of times
</RootLevel>
我使用 xsd.exe 实用程序从我的 xml 架构定义文件生成了一些 类。它们看起来像:
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://MyCompany.com/MySchema.xsd")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.MyCompany.com/MySchema.xsd", IsNullable = false)]
public partial class RootLevel
{
private List<Level1> level1Field;
public List<Level1> Level1Field
{
get { return this.level1Field;}
set {this.level1Field = value;}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.MyCompany.com/MySchema.xsd")]
public partial class Level1
{
private List<Level2> level2Field;
public List<Level2> Level2Field
{
get { return this.level2Field;}
set {this.level2Field = value;}
}
/* other properties on Level1 go here*/
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.MyCompany.com/MySchema.xsd")]
public partial class Level2
{
/* properties on Level2 go here*/
}
我通过使用 XmlWriter.WriteStartElement() 写出 RootLevel 元素来制作这个文件,然后我通过创建 Level1 对象并使用 XmlSerializer 序列化它们来写出文件的其余部分。
目标
我希望文件仅在 RootLevel 元素上具有命名空间。
如果你有兴趣,这是我到目前为止尝试过的:
起点
一开始,我的 RootLevel 元素没有任何命名空间。 我的 Level1 和 Level2 元素有命名空间。
第 1 步:
我尝试通过覆盖 类 Level1 和 Level2 的 XmlTypeAttributes 上的名称空间,从 Level1 和 Level2 元素中删除名称空间。
XmlTypeAttribute attribute = new XmlTypeAttribute();
attribute.Namespace = string.Empty;
XmlAttributes attributes = new XmlAttributes();
attributes.XmlType = attribute;
XmlAttributeOverrides overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Level1), attributes);
overrides.Add(typeof(Level2), attributes);
this.xmlSerializer = new XmlSerializer(typeof(Level1), overrides);
步骤 1 结果
名称空间已从 Level2 中删除,但未从 Level1 中删除。
步骤 2
添加了更多代码以尝试从 Level1 中删除命名空间。我尝试使用 XmlSerializer.Serialize() 方法的名称空间参数来使用空名称空间。注意 "level1" 是 "Level1".
类型的对象XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add("", "");
this.xmlSerializer.Serialize(this.xmlFileWriter, level1, namespaces);
步骤 2 结果
命名空间从 Level1 和 Level2 中删除。到目前为止,一切都很好!现在我需要做的就是将命名空间的东西添加到 RootLevel。
步骤 3
由于 RootLevel 未序列化,我添加了一些 XmlWriter 代码以尝试将命名空间添加到 RootLevel。
string defaultNamespace = "http://www.MyCompany.com/MySchema.xsd";
this.xmlFileWriter.WriteStartElement("RootLevel", defaultNamespace);
this.xmlFileWriter.WriteAttributeString("xmlns", "xsi", "", "http://www.w3.org/2001/XMLSchema-instance");
this.xmlFileWriter.WriteAttributeString("xmlns", "xsd", "", "http://www.w3.org/2001/XMLSchema");
步骤 3 结果
名称空间已添加到 RootLevel。耶!。 但是,现在每个 Level1 元素都有一个 xmlns="" 属性。哇!
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.MyCompany.com/MySchema.xsd">
<Level1 xmlns="">
<Level2>
</Level2>
</Level1 >
<Level1 xmlns="">
<Level2>
</Level2>
</Level1 >
etc. repeats hundreds of times
</RootLevel>
那为什么会这样?
你没有 post 你的原始代码所以我不知道你到底哪里错了,但我能够得到你想要的 XML 如下:
提取静态助手 class
XmlNamespaces
来保存命名空间字符串并将它们声明为const
字符串。在您的问题中,您有时使用"http://MyCompany.com/MySchema.xsd"
但有时使用"http://www.MyCompany.com/MySchema.xsd"
。这可能只是问题中的错字,但如果您的代码不一致地使用这些将导致错误。除了
之外,对classXmlTypeAttribute
Level1
应用XmlRootAttribute
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)] [System.Xml.Serialization.XmlRootAttribute(Namespace = XmlNamespaces.Default, IsNullable = false)] public partial class Level1 { // Properties }
写入根元素时,将默认命名空间字符串传递给
XmlWriter.WriteStartElement(string, string)
。
整体代码如下:
public static class XmlNamespaces
{
public const string Default = "http://MyCompany.com/MySchema.xsd";
public const string xsi = "http://www.w3.org/2001/XMLSchema-instance";
public const string xsd = "http://www.w3.org/2001/XMLSchema";
public static XmlSerializerNamespaces XmlSerializerNamespaces
{
get
{
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("", XmlNamespaces.Default);
namespaces.Add("xsi", XmlNamespaces.xsi);
namespaces.Add("xsd", XmlNamespaces.xsd);
return namespaces;
}
}
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = XmlNamespaces.Default, IsNullable = false)] // Added this and used const string from XmlNamespaces class
public partial class Level1
{
private List<Level2> level2Field;
public List<Level2> Level2Field
{
get { return this.level2Field; }
set { this.level2Field = value; }
}
/* other properties on Level1 go here*/
}
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = XmlNamespaces.Default)] // Used const string from XmlNamespaces class
public partial class Level2
{
/* properties on Level2 go here*/
}
public static class XmlSerializationUtilities
{
public static void WriteList<TItem>(string rootName, XmlSerializerNamespaces namespaces, IEnumerable<TItem> list, TextWriter textWriter)
{
var namespaceList = namespaces.ToArray();
string defaultNamespace = null;
foreach (var ns in namespaceList)
{
if (string.IsNullOrEmpty(ns.Name))
{
defaultNamespace = ns.Namespace;
break;
}
}
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = " ";
using (var writer = XmlWriter.Create(textWriter, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement(rootName, defaultNamespace);
foreach (var ns in namespaceList)
if (!string.IsNullOrEmpty(ns.Name))
writer.WriteAttributeString("xmlns", ns.Name, null, ns.Namespace);
var serializer = new XmlSerializer(typeof(TItem));
foreach (var item in list)
{
serializer.Serialize(writer, item);
}
writer.WriteEndElement();
writer.WriteEndDocument();
}
}
}
public static class TestClass
{
public static void Test()
{
var list = new List<Level1> { new Level1 { Level2Field = new List<Level2> { new Level2(), new Level2() } }, new Level1 { Level2Field = new List<Level2> { new Level2(), new Level2(), new Level2(), new Level2() } } };
string xml;
using (var writer = new StringWriter())
{
XmlSerializationUtilities.WriteList("RootLevel", XmlNamespaces.XmlSerializerNamespaces, list, writer);
xml = writer.ToString();
Debug.WriteLine(xml);
}
}
}
输出为
<?xml version="1.0" encoding="utf-16"?>
<RootLevel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://MyCompany.com/MySchema.xsd">
<Level1>
<Level2Field>
<Level2 />
<Level2 />
</Level2Field>
</Level1>
<Level1>
<Level2Field>
<Level2 />
<Level2 />
<Level2 />
<Level2 />
</Level2Field>
</Level1>
</RootLevel>