像这样定义你的类型:
[XmlRoot("Method")]
public class MyMethod
{
[XmlAttribute]
public String Name { get; set; }
[XmlElement]
public int DEF { get; set; }
}
[XmlRoot("Request", Namespace="http://mynamespace")]
public class MyRequest
{
[XmlElement]
public String ABC { get; set; }
[XmlElement(Namespace="http://myothernamespace")]
public MyMethod Method { get; set; }
}
支持代码:
static TextWriter GetWriter(bool wantSave)
{
if (wantSave)
{
var fs = new FileStream(StorageFile, FileMode.Create);
return new StreamWriter(fs, new UTF8Encoding());
}
return Console.Out;
}
private static void ShoworSave(MyRequest r, bool wantSave)
{
if (r==null)
{
Console.WriteLine(" --null--");
return;
}
Console.WriteLine("\n");
var writerSettings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true
};
using (XmlWriter xmlWriter =
XmlWriter.Create(GetWriter(wantSave), writerSettings))
{
XmlSerializer ser = new XmlSerializer(r.GetType());
var ns = new XmlSerializerNamespaces();
ns.Add("", "http://mynamespace"); // default xmlns
ser.Serialize(xmlWriter, r, ns);
}
Console.WriteLine("\n");
}
然后像这样使用:
var request = new MyRequest
{
ABC = "HelloWorld",
Method = new MyMethod
{
Name="TEST",
DEF=123456
}
};
SaveOrShow(request, false);
结果:
<Request xmlns="http://mynamespace">
<ABC>HelloWorld</ABC>
<Method Name="TEST" xmlns="http://myothernamespace">
<DEF>123456</DEF>
</Method>
</Request>
讨论
Xml 序列化程序允许您指定命名空间映射,从而可以为序列化输出提供命名空间前缀列表和它们映射到的实际命名空间。要设置默认的 xml 命名空间及其前缀,请使用前缀“”(空字符串)。
所以我使用的代码指定了默认命名空间。
我还使用适当的 xml 序列化程序属性修饰了各种类型和成员,以获得正确的命名空间。
乍一看,您可能认为在代码中的几个不同位置使用 xml 命名空间字符串(在您的示例中为“http://mynamespace”)违反了干净编码的“不要重复自己”格言。但这不是真的。在我使用它的一个地方,它设置了该类型的 XML 命名空间。另一方面,它为序列化程序指定了默认的 xml 命名空间。
如果我没有指定后者,那么你会得到一个前缀;这将为您提供语义上等效的 xml 信息集,但是因为您说您的接收器应用程序不是真正的 xml 感知的,所以它会破坏该接收器。
此外,关于您关于 xsd.exe 和代码生成的问题,不确定您在做什么,但请考虑一下:Xsd.exe 只是一个工具。获取该工具的输出并对其进行调整、编辑并没有错。如果您的类型相对简单,您可能会发现只在 C# 中定义类型会更容易,正如我在上面所展示的。如果您很喜欢将 XSD 作为源代码,那么您将需要依赖 xsd.exe 工具。在这种情况下,您需要在 xsd 文档的适当位置指定这些名称空间。您选择哪个选项取决于您。