如何在Java中有选择地合并两个xml文件

时间:2019-05-08 12:42:52

标签: java xml merge

我有两个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>

任何帮助(请菜鸟级别)都将不胜感激。

1 个答案:

答案 0 :(得分:0)

我认为您没有完全指定要求(一个示例没有制定规范),但是如果我们假设第一个源文档正好包含一个/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>

,您可以使用Saxon库从Java运行以下代码:

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);

如果您更喜欢使用JDK随附的XSLT 1.0处理器,那也是可能的,它只需要多一点代码即可。与尝试直接使用低级DOM API进行操作相比,代码仍然要少得多。