如何使用XmlSerializer在大型文档中插入节点 [英] How to insert a node in a large document using XmlSerializer

查看:29
本文介绍了如何使用XmlSerializer在大型文档中插入节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个很大的XML文档,我想使用 XmlSerializer 类插入新元素,其内容来自使用xsd.exe生成的.NET类实例.

I have a large XML document and I want to use the XmlSerializer class to insert new elements whose content comes from a .NET class instance generated using xsd.exe.

这是对如何使用XmlSerializer对大型文档中的节点反序列化的后续步骤,并使用该问题中描述的相同xsd和生成的类.

This is a follow-up to the question How to deserialize a node in a large document using XmlSerializer, and uses the same xsd and generated classes that are described in that question.

让我们说,在我的示例XML中,我想将福特的汽车换成宝马.我尝试了以下代码:

Let's say that in my sample XML I want to exchange my Ford car for a BMW. I've tried the following code:

static string XmlContent = @"
    <RootNode xmlns=""http://MyNamespace"">
        <Cars>
        <Car make=""Volkswagen"" />
        <Car make=""Ford"" />
        <Car make=""Opel"" />
        </Cars>
    </RootNode>";

private static void TestWriteMcve()
{
    var doc = new XmlDocument();
    doc.LoadXml(XmlContent);
    var nsMgr = new XmlNamespaceManager(doc.NameTable);
    nsMgr.AddNamespace("myns", "http://MyNamespace");

    var node = doc.DocumentElement.SelectSingleNode("myns:Cars/myns:Car[@make='Ford']", nsMgr);
    var parent = node.ParentNode;
    var carSerializer = new XmlSerializer(typeof(Car));

    using (var writer = node.CreateNavigator().InsertAfter())
    {
        // WriteWhitespace needed to avoid error "WriteStartDocument cannot
        // be called on writers created with ConformanceLevel.Fragment."
        writer.WriteWhitespace("");
        var newCar = new Car { make = "BMW" };
        carSerializer.Serialize(writer, newCar);
    }
    parent.RemoveChild(node);
    Console.WriteLine(parent.OuterXml);
}

我得到的结果接近我想要的:

The result I get is close to what I want:

<Cars xmlns="http://MyNamespace">
  <Car make="Volkswagen" />
  <Car xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" make="BMW" xmlns="" />
  <Car make="Opel" />
</Cars>

,除了添加的元素上所有不需要的 xmlns:... 属性外.它们来自哪里,我如何摆脱它们?

except for all those unwanted xmlns:... attributes on the element that was added. Where did they come from and how can I get rid of them?

推荐答案

中所述,在在.NET中序列化一个对象? XmlSerializer 在序列化时总是会有益地添加 xsi xsd 命名空间.如果您不希望这样做,则需要调用 Serialize 的重载,在其中可以指定所需的初始名称空间,例如 XmlSerializer.Serialize(XmlWriter,Object,XmlSerializerNamespaces) .以下扩展方法可以解决问题:

As explained in Omitting all xsi and xsd namespaces when serializing an object in .NET?, XmlSerializer will always helpfully add the xsi and xsd namespaces when serializing. If you don't want that, you need to call an overload of Serialize where the required initial namespaces can be specified, e.g. XmlSerializer.Serialize(XmlWriter, Object, XmlSerializerNamespaces). The following extension method does the trick:

public static class XmlNodeExtensions
{
    public static XmlNode ReplaceWithSerializationOf<T>(this XmlNode node, T replacement)
    {
        if (node == null)
            throw new ArgumentNullException();
        var parent = node.ParentNode;
        var serializer = new XmlSerializer(replacement == null ? typeof(T) : replacement.GetType());

        using (var writer = node.CreateNavigator().InsertAfter())
        {
            // WriteWhitespace needed to avoid error "WriteStartDocument cannot
            // be called on writers created with ConformanceLevel.Fragment."
            writer.WriteWhitespace("");

            // Set up an appropriate initial namespace.
            XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
            ns.Add(node.GetNamespaceOfPrefix(node.NamespaceURI), node.NamespaceURI);

            // Serialize
            serializer.Serialize(writer, replacement, ns);
        }

        var nextNode = node.NextSibling;
        parent.RemoveChild(node);
        return nextNode;
    }
}

然后按如下所示使用它:

Then use it as follows:

var newCar = new Car { make = "BMW" };
var node = doc.DocumentElement.SelectSingleNode("myns:Cars/myns:Car[@make='Ford']", nsMgr);
node = node.ReplaceWithSerializationOf(newCar);
var parent = node.ParentNode;

然后,为 doc 生成的XML将是:

Afterwards, the XML generated for doc will be:

<RootNode xmlns="http://MyNamespace">
  <Cars>
    <Car make="Volkswagen" />
    <Car make="BMW" />
    <Car make="Opel" />
  </Cars>
</RootNode>

示例工作 .Net小提琴.

这篇关于如何使用XmlSerializer在大型文档中插入节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆