0

我遇到以下问题。每当我在我的 C# 类中使用默认 XML 序列化时,命名空间xsixsd.NET 序列化引擎都会自动添加。但是,当通过 定义序列化时IXmlSerializable,不会添加命名空间。

示例:此代码:

class Program
{
    static void Main(string[] args)
    {
        OutputSerialized(new Outer() { Inner = new Inner() });
        OutputSerialized(new OuterCustom() { Inner = new Inner() });
    }

    static void OutputSerialized<T>(T t)
    {
        var sb = new StringBuilder();
        using (var textwriter = new StringWriter(sb))
            new XmlSerializer(typeof(T)).Serialize(textwriter, t);
        Console.WriteLine(sb.ToString());
    }
}

[Serializable] public class Inner { }

[Serializable] public class Outer { public Inner Inner { get; set; } }

public class OuterCustom : IXmlSerializable
{
    public Inner Inner;

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement("Inner");
        new XmlSerializer(typeof(Inner)).Serialize(writer, Inner);
        writer.WriteEndElement();
    }

    public System.Xml.Schema.XmlSchema GetSchema() { return null; }
    public void ReadXml(System.Xml.XmlReader reader) { /**/ }
}

产生以下输出:

<?xml version="1.0" encoding="utf-16"?>
<Outer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Inner />
</Outer>
<?xml version="1.0" encoding="utf-16"?>
<OuterCustom>
  <Inner>
    <Inner xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
  </Inner>
</OuterCustom>

您可以看到OuterCustom的序列化形式缺少xsdandxsi命名空间。

我怎样才能使我的OuterCustom行为方式与我相同Outer?我的代码中是否缺少某些内容?我做错了自定义序列化吗?

这里有很多关于如何摆脱额外命名空间的问题,但似乎没有人问过如何让它们回来

4

1 回答 1

1

首先 - 对于兼容的 XML 解析器,提到的 XML 版本之间没有区别。只要节点关联了正确的命名空间,是否/如何/在哪里定义命名空间前缀并不重要。

由于这个问题明确地是关于在哪里放置命名空间声明的样式,所以可以自己调用什么是好的,什么不是。在这种特殊情况下,目标是避免重复的xmlns属性并将它们在树中移到更高的位置。

只要它们不在同一个节点上发生冲突,就可以在任何需要的地方编写 xmlns 属性。使用XmlWriter.WriteAttributeString方法添加它们:

writer.WriteAttributeString(
  "xmlns", "prefix", null, "urn:mynamespace");

为避免重复声明 - 检查是否已使用XmlWriter.LookupPrefix为给定命名空间定义前缀

确保xsdxsi前缀的示例代码(由 Vlad 提供):

const string xsiNamespace = System.Xml.Schema.XmlSchema.InstanceNamespace;
const string xsdNamespace = System.Xml.Schema.XmlSchema.Namespace;

public static void EnsureDefaultNamespaces(System.Xml.XmlWriter writer)
{
   if (writer.LookupPrefix(xsiNamespace) == null)
       writer.WriteAttributeString("xmlns", "xsi", null, xsiNamespace);
   if (writer.LookupPrefix(xsdNamespace) == null)
       writer.WriteAttributeString("xmlns", "xsd", null, xsdNamespace);
}

如果希望进行更多更改以实现漂亮的 XML,则另一种方法是允许序列化完成,而不是处理 XML 以调整前缀定义(即标准化为所需的前缀,收集所有名称空间并在顶部定义所有内容)。可以使用 C# 代码读取 XML,甚至可以创建 XSLT 转换。

于 2013-11-28T07:22:11.730 回答