Объединить XML-документы

Мне нужно "объединить" два XML-документа, перезаписав перекрывающиеся атрибуты и элементы. Например, если у меня есть document1:

<mapping>
    <key value="assigned">
        <a/>
    </key>
    <whatever attribute="x">
        <k/>
        <j/>
    </whatever>
</mapping>

и document2:

<mapping>
    <key value="identity">
        <a/>
        <b/>
    </key>
</mapping>

Я хочу объединить эти два элемента так:

<mapping>
    <key value="identity">
        <a/>
        <b/>
    </key>
    <whatever attribute="x">
        <k/>
        <j/>
    </whatever>
</mapping>

Я предпочитаю решения Java или XSLT -based, ant подойдет, но если есть простой способ сделать это в Rake, Ruby или Python, пожалуйста, не стесняйтесь :-)

ОБНОВЛЕНИЕ: на самом деле я бы предпочел использовать автоматизированный инструмент/сценарий, даже писать его самостоятельно, потому что ручное объединение около 30 файлов XML немного громоздко... :-(

Ответы

Ответ 1

Если вам нравится XSLT, есть хорошее слияние script, которое я использовал ранее: страница Oliver XSLT

Ответ 2

Я знаю, что это старый поток, но Проект: Merge может сделать это за вас. Он может объединить два XML файла вместе и может быть запущен из командной строки, поэтому вы можете объединить все вместе, запустить его и разрешить любые конфликты (например, изменение значения атрибута "ключ" в приведенном выше примере) вручную с помощью несколько кликов. (Вы можете сказать, что он работает тихо, обеспечивая отсутствие конфликтов.)

Он может выполнять двусторонние и трехсторонние сравнения файлов XML и двухсторонние и трехсторонние слияния. (Если трехсторонняя операция предполагает, что два файла, которые сравниваются/объединены, имеют общего предка.)

Ответ 3

Проверьте XmlCombiner, которая является библиотекой Java, которая реализует слияние XML именно таким образом. Он основан на похожей функциональности, предоставляемой библиотекой plexus-utils.

Соглашение по умолчанию в XmlCombiner - перезаписывать перекрывающиеся атрибуты и элементы. Но точное поведение слияния может быть изменено с помощью специальных атрибутов 'Объединить.сам' и 'Объединять.чайлдрен'.

Использование:

import org.atteo.xmlcombiner.XmlCombiner;

// create combiner
XmlCombiner combiner = new XmlCombiner();
// combine files
combiner.combine(firstFile);
combiner.combine(secondFile);
// store the result
combiner.buildDocument(resultFile);

Отказ от ответственности: я автор.

Ответ 4

Не уверен, хотите ли вы сделать это программно или нет.

Изменить: Ах, я разместил это перед Редактированием. Разве я не выгляжу теперь как идиот!;)

Если вы просто хотите объединить два файла вместе, у IBM есть XML Diff and Merge Tool, а также Altova DiffDog.

Ответ 5

(также с использованием таблиц стилей Oliver XSLT)

Объединение XSLT из PowerShell:

param(
[Parameter(Mandatory = $True)][string]$file1,
[Parameter(Mandatory = $True)][string]$file2,
[Parameter(Mandatory = $True)][string]$path
)

# using only abs paths .. just to be safe
$file1 = Join-Path $(Get-Location) $file1
$file2 = Join-Path $(Get-Location) $file2
$path = Join-Path $(Get-Location) $path

# awesome xsl stylesheet from Oliver Becker
# http://web.archive.org/web/20160502194427/http://www2.informatik.hu-berlin.de/~obecker/XSLT/merge/merge.xslt
$xsltfile = Join-Path $(Get-Location) "merge.xslt"

$XsltSettings = New-Object System.Xml.Xsl.XsltSettings
$XsltSettings.EnableDocumentFunction = 1

$xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
$xslt.Load($xsltfile , $XsltSettings, $(New-Object System.Xml.XmlUrlResolver))

[System.Xml.Xsl.XsltArgumentList]$al = [System.Xml.Xsl.XsltArgumentList]::new()
$al.AddParam("with", "", $file2)
$al.AddParam("replace", "", "true")

[System.Xml.XmlWriter]$xmlwriter = [System.Xml.XmlWriter]::Create($path)
$xslt.Transform($file1, $al, $xmlwriter)

Использование простого саксонского языка:

java -jar saxon9he.jar .\FileA.xml .\merge.xslt with=FileB.xml replace=true