如何在从XPathNavigator.AppendChild()创建时设置XmlWriter.XmlWriterSett

本文关键字:创建 设置 XmlWriter XmlWriterSett XPathNavigator AppendChild | 更新日期: 2023-09-27 18:24:07

我需要将XmlWriter的XmlWriterSettings的OmitXmlDeclaration属性设置为false,以便不创建XML声明。问题是,我通过调用XPathNavigator.AppendChild()方法创建了XmlWriter。以下代码:

    public String GetEntityXml<T>(List<T> entities)
    {
        XmlDocument xmlDoc = new XmlDocument();
        XPathNavigator nav = xmlDoc.CreateNavigator();
        using (XmlWriter writer = nav.AppendChild())
        {
            XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "_LIST"));
            ser.Serialize(writer, entities);
        }
        StringWriter stringWriter = new StringWriter();
        XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
        xmlDoc.WriteTo(xmlTextWriter);
        string resultString = stringWriter.ToString();
        stringWriter.Close();
        xmlTextWriter.Close();
        return resultString;
    }

知道如何序列化List而不使用XML声明吗?

如何在从XPathNavigator.AppendChild()创建时设置XmlWriter.XmlWriterSett

执行您的代码时,我没有得到XML声明。序列化List<int>给了我:

<Int32_LIST xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <int>5</int>
  <int>7</int>
  <int>2</int>
</Int32_LIST>

注意,OmitXmlDeclaration所指的"XML声明"通常类似于:

<?xml version="1.0" encoding="UTF-8" ?>

如果您引用的是xmlns部分,那么这些部分被称为"XML命名空间声明",可以通过使用默认的空命名空间初始化XmlSerializerNamespaces实例并将其传递给Serialize方法来消除:

XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "_LIST"));
var namespaces = new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") });
ser.Serialize(writer, entities, namespaces);

下面是一个缩短的实现,它可以获得与您的代码相同的结果:

public String GetEntityXml<T>(List<T> entities)
{
    var sb = new StringBuilder();
    var settings = new XmlWriterSettings { OmitXmlDeclaration = true };
    using (XmlWriter writer = XmlWriter.Create(sb, settings))
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute(typeof(T).Name + "_LIST"));
        var namespaces = new XmlSerializerNamespaces(new[] { new XmlQualifiedName("", "") });
        ser.Serialize(writer, entities, namespaces);
    }
    return sb.ToString();
}

尝试这种方法(为了可读性,切换到var):

public String GetEntityXml<T>(List<T> entities)
{
    var xmlDoc = new XmlDocument();
    var nav = xmlDoc.CreateNavigator();
    using (var sw = new StringWriter())
    {
        //Create an XmlWriter that will omit xml declarations
        var s = new XmlWriterSettings{ OmitXmlDeclaration = true };
        using (var xmlWriter = XmlWriter.Create(sw, s))
        {
            //Use the following to serialize without namespaces
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            var ser = new XmlSerializer(typeof(List<T>),
                          new XmlRootAttribute(typeof(T).Name + "_LIST"));
            ser.Serialize(xmlWriter, entities, ns);
        }
        //Pass xml string to nav.AppendChild()
        nav.AppendChild(sw.ToString());
    }
    using (var stringWriter = new StringWriter())
    {
        using (var xmlTextWriter = XmlWriter.Create(stringWriter))
        {
            xmlDoc.WriteTo(xmlTextWriter);
        }
        return stringWriter.ToString();
    }
}

您可以单独创建XmlWriter,然后只使用nav.AppendChild(string)将XML写入xmlDoc,而不是使用nav.AppendChild()来创建XmlWriter。当您自己创建XmlWriter时,可以省略XML声明。此外,在序列化时,您可能希望使用XmlSerializerNamespaces类省略xmlns:xsixmlns:xsd名称空间。