Как выборочно объединить два файла XML в Java - PullRequest
0 голосов
/ 08 мая 2019

У меня есть два XML-файла (источник и место назначения), и я хочу выборочно объединить части источника в место назначения, используя Java.Файлы имеют одинаковую структуру, но содержат вложенные теги с одинаковыми именами на разных уровнях (пример ниже).

У источника и назначения может быть несколько /Root/folders/folder Я хочу выбрать из источника (с указанной подписью)) и объединить это с тем, что находится в пункте назначения.Если в месте назначения уже есть контент, его нельзя перезаписывать;исходный контент должен быть добавлен.В приведенном ниже примере результат будет содержать <folder caption="TestBlock" description="desc" moniker=""> с несколькими <folders>

. Я не эксперт ни по Java, ни по XML (но босс сказал, что сделайте это, так что ...).

Google показал много примеров выполнения прямого добавления из файла A в файл B, где нет сложных вложенных структур, но они не решают мою проблему.

Исходный файл:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Root signature="{9252F941}" version="11.40">
    <folders>
        <folder caption="TestBlock" description="desc" moniker="">
            <folders>
                <folder caption="tb_insert" description="desc" moniker="">
                    <folders>
                        <folder caption="000_Test" description="desc" moniker="">
                            <references>
                                <ref key="{somekey}" />
                            </references>
                        </folder>
                    </folders>
                    <references>
                        <ref key="{somekey}" />
                    </references>
                </folder>
            </folders>
        </folder>
        <folder caption="AnotherBlock" description="desc" moniker="">
            <folders>
                <folder caption="abc" description="desc" moniker="">
                    <references>
                        <ref key="{somekey}" />
                    </references>
                </folder>
            </folders>
        </folder>
    </folders>
</Root>

Файл назначения:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Root signature="{9252F941}" version="11.40">
    <folders>
        <folder caption="Core" description="desc" moniker="" />
        <folder caption="TestBlock" description="desc" moniker="">
            <folders>
                <folder caption="000_Temp" description="desc" moniker="">
                    <folders>
                        <folder caption="000_Temp2" description="desc" moniker="">
                            <references>
                                <ref key="{somekey}" />
                            </references>
                        </folder>
                    </folders>
                </folder>
            </folders>
            <references>
                <ref key="{somekey}" />
            </references>
        </folder>
    </folders>
</Root>

Желаемый вывод:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Root signature="{9252F941}" version="11.40">
    <folders>
        <folder caption="Core" description="desc" moniker="" />
        <folder caption="TestBlock" description="desc" moniker="">
            <folders>
                <folder caption="tb_insert" description="desc" moniker="">
                    <folders>
                        <folder caption="000_Test" description="desc" moniker="">
                            <references>
                                <ref key="{somekey}" />
                            </references>
                        </folder>
                    </folders>
                    <references>
                        <ref key="{somekey}" />
                    </references>
                </folder>
            </folders>
            <folders>
                <folder caption="000_Temp" description="desc" moniker="">
                    <folders>
                        <folder caption="000_Temp2" description="desc" moniker="">
                            <references>
                                <ref key="{somekey}" />
                            </references>
                        </folder>
                    </folders>
                </folder>
            </folders>
            <references>
                <ref key="{somekey}" />
            </references>
        </folder>
    </folders>
</Root>

Любая помощь (уровень noob, пожалуйста) будет оценена.

1 Ответ

0 голосов
/ 08 мая 2019

Я не думаю, что вы указали требования полностью (один пример не дает спецификации), но если мы предположим, что первый исходный документ содержит ровно один /Root/folders/folder и его содержимое должно заменить одно- и только //folder в целевом документе с соответствующим заголовком, тогда логика может быть записана в XSLT 3.0 как

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:mode on-no-match="shallow-copy"/>
    <xsl:variable name="replacement" select="doc('source.xml')/Root/folders/folder"/>
    <xsl:template match="folder[@caption = $replacement/$caption]">
      <xsl:copy-of select="$replacement"/>
    </xsl:template>
</xsl:transform>

и вы можете запустить это из Java, используя библиотеку Saxon с кодом:

Processor proc = new Processor(false);
XsltCompiler comp = proc.newXsltCompiler();
Xslt30Transformer trans = comp.compile("stylesheet.xsl").load30();
Serailizer out = proc.newSerializer(new File("output.xml"));
trans.applyTemplates(new StreamSource("destination.xml"), out);

Если вы предпочитаете использовать процессор XSLT 1.0, поставляемый с JDK, то это тоже возможно, просто потребуется немного больше кода. По-прежнему будет гораздо меньше кода, чем пытаться сделать это напрямую с помощью низкоуровневого API DOM.

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