Объединить два файла XML, один из которых не соответствует, в C # - PullRequest
2 голосов
/ 04 апреля 2011

У меня есть два 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-файла, с тегом a и вокруг всего лота и заголовком вверху.

Есть идеи?

Спасибо, Рик

Ответы [ 3 ]

6 голосов
/ 04 апреля 2011

На мой взгляд, предоставленный вами XML-файл просто отлично.Я полагаю, что вы используете следующий код и вообще не используете класс Dataset:

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));
4 голосов
/ 04 апреля 2011

Я подозреваю, что решение заключается в предоставлении схемы. DataSet.Merge не знает, что делать с двумя наборами элементов с одинаковыми именами. Он пытается вывести схему, но здесь это не так хорошо работает.

Согласно этой теме в MSDN , это ограничение класса DataSet:

Класс DataSet в .NET 2.0 (Visual Studio 2005) по-прежнему имеет ограничение не поддерживать разные вложенные таблицы с одинаковыми именами. Поэтому вам придется ввести преобразование XML для предварительной обработки XML (и схем) перед загрузкой их в DataSet.

Конечно, из-за формулировки кажется , как если бы более новая версия могла это исправить. К сожалению, это может быть не так, поскольку первоначальный ответ был опубликован еще в 2005 году.

Эта статья базы знаний , по-видимому, указывает на то, что это поведение "разработано", хотя и в несколько ином контексте.

Лучшее объяснение того, почему происходит такое поведение, также дано в этой теме :

Когда ADO читает XML в DataSet, он создает DataTables, чтобы содержать каждый тип элемента, с которым он сталкивается. Каждая таблица уникально идентифицируется по имени. Вы не можете иметь две разные таблицы с именем "PayList".

Кроме того, данная таблица может иметь любое количество родительских таблиц, но только одно из ее родительских отношений может быть вложенным - в противном случае данная запись будет записана в XML несколько раз, как дочерний элемент каждой из ее родительских строк. .

Чрезвычайно удобно, что метод ReadXml DataSet может вывести схему DataSet, когда он читает входные данные, но XML должен соответствовать определенным ограничениям, если он будет читабельным. XML у вас нет. Таким образом, у вас есть две альтернативы: вы можете изменить XML или написать собственный метод для заполнения DataSet.

Если бы это был я, я бы написал XSLT-преобразование, которое бы взяло входной XML и превратило элементы PayList в элементы MatrixPayList или NonMatrixPaylist. Затем я передаю его вывод в DataSet.

Использование XmlDocument или XDocument для чтения и манипулирования файлами XML - это еще один возможный обходной путь. Для примера см. Объединение двух XML-файлов LINQ

0 голосов
/ 08 апреля 2015

Я нашел решение, использующее сериализацию, чтобы сначала вывести схему, затем сериализовать схему и удалить ограничения отношений (это заставляет DataSet думать, что ИТ-специалист создал набор данных.), А затем загружать эту новую схему в DataSet.

Этот новый набор данных сможет загружать оба ваших XML-файла.Подробнее об этом трюке: Проблема сериализации при использовании метода WriteXML

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...