繁体   English   中英

在C#中合并两个XML文件,其中一个是不符合的

[英]Merge two XML files, one of which is non-conformant, in C#

我有两个XML文件需要合并到一个文件中。 当我尝试合并它们时,我得到一个错误,说它们中的一个不符合。

违规的XML文件看起来像:

<letter>
    <to>
        <participant>
            <name>Joe Bethersonton</name>
            <PostalAddress>Apartment 23R, 11454 Pruter Street</PostalAddress>
            <Town>Fargo, North Dakota, USA</Town>
            <ZipCode>50504</ZipCode>
        </participant>
    </to>
    <from>
        <participant>
            <name>Jon Doe</name>
            <PostalAddress>52 Generic Street</PostalAddress>
            <Town>Romford, Essex, UK</Town>
            <ZipCode>RM11 2TH</ZipCode>
        </participant>
    </from>
</letter>

我正在尝试使用以下代码段合并这两个文件:

try
{
    Dataset ds = new DataSet();
    Dataset ds2 = new DataSet();
    XmlTextReader reader1 = new XmlTextReader("C:\\File1.xml");
    XmlTextReader reader2 = new XmlTextReader("C:\\File2.xml");
    ds.ReadXml(reader1);
    ds2.ReadXml(reader2);
    ds.Merge(ds2);
}
catch(System.Exception ex)
{
    Console.WriteLine(ex.Message);
}

这会出现以下错误:

同一个表'参与者'不能是两个嵌套关系中的子表。

这两个XML文件都以UTF-16编码,这使得它们通过简单的文本读写很难组合。

我需要的最终结果是一个XML文件,其中第一个XML文件的内容后跟第二个XML文件的内容,整个批次周围有一个标记,顶部有一个标题。

有任何想法吗?

谢谢,Rik

在我看来,你提供的XML就好了。 我建议你使用以下代码,根本不使用数据集类:

XDocument doc1 = XDocument.Load("C:\\File1.xml");
XDocument doc2 = XDocument.Load("C:\\File2.xml");
var result = new XDocument(new XElement("Root", doc1.Root, doc2.Root));

result将包含一个XML文档,其中“Root”作为根标记,然后是文件1的内容,后跟文件2的内容。

更新:
如果需要使用XmlDocument ,可以使用以下代码:

XmlDocument doc1 = new XmlDocument();
XmlDocument doc2 = new XmlDocument();
doc1.Load("C:\\File1.xml");
doc2.Load("C:\\File2.xml");
XmlDocument result = new XmlDocument();
result.AppendChild(result.CreateElement("Root"));
result.DocumentElement.AppendChild(result.ImportNode(doc1.DocumentElement, true));
result.DocumentElement.AppendChild(result.ImportNode(doc2.DocumentElement, true));

我怀疑解决方案是提供架构。 DataSet.Merge不知道如何处理两组具有相同名称的元素。 它试图推断一个模式,但这在这里效果不佳。

根据MSDN上的这个帖子 ,这是DataSet类的限制:

.NET 2.0(Visual Studio 2005)中的DataSet类仍然具有不支持具有相同名称的不同嵌套表的限制。 因此,在将XML(和模式)加载到DataSet之前,必须引入XML转换来预处理XML(和模式)。

当然,措辞的方式使它看起来像一个较新的版本可能已经解决了这个问题。 不幸的是,情况可能并非如此,因为最初的答案是在2005年发布的。

这篇知识库文章似乎表明这种行为是“按设计”的,虽然情况略有不同。

此线程还给出了更好地解释为什么会发生这种行为的原因:

当ADO将XML读入DataSet时,它会创建DataTables以包含它遇到的每种类型的元素。 每个表都由其名称唯一标识。 您不能有两个名为“PayList”的不同表。

此外,给定的表可以包含任意数量的父表,但只能嵌套其父关系中的一个 - 否则,给定的记录将多次写入XML,作为其每个父行的子项。

DataSet的ReadXml方法在读取其输入时可以推断出DataSet的模式是非常方便的,但是如果XML可读的话必须符合某些约束。 你得到的XML没有。 因此,您有两种选择:可以更改XML,也可以编写自己的方法来填充DataSet。

如果是我,我会编写一个XSLT转换,它将输入XML和PayList元素转换为MatrixPayList或NonMatrixPaylist元素。 然后我将其输出传递给DataSet。

使用XmlDocumentXDocument读入和操作XML文件是另一种可能的解决方法。 有关示例,请参阅合并两个xml文件LINQ

我找到了一个解决方案,使用Serialization首先推断出架构,然后序列化架构并删除关系约束(这会让DataSet误以为IT已经创建了数据集。),然后将这个新架构加载到DataSet中。

这个新数据集将能够加载您的xml文件。 这个技巧背后的更多细节: 使用WriteXML方法时的序列化问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM