【问题标题】:How to selectively merge two xml files in java如何在java中选择性地合并两个xml文件
【发布时间】:2019-09-26 04:59:47
【问题描述】:

我有两个 XML 文件(源文件和目标文件),并希望使用 Java 有选择地将部分源文件合并到目标文件中。这些文件具有相同的结构,但包含在不同级别具有相同名称的嵌套标签(示例如下)。

源和目标可以有多个/Root/folders/folder 我想从源中选择(带有指定的标题)并将其与目标中的任何内容合并。如果目的地已经有内容,则不得覆盖;必须添加源内容。在下面的示例中,结果将包含一个 <folder caption="TestBlock" description="desc" moniker=""> 和多个 <folders>

我不是 Java 或 XML 方面的专家(但老板说要做,所以……)。

谷歌搜索显示了许多从文件 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>

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

【问题讨论】:

标签: java xml merge


【解决方案1】:

我不认为你已经完全指定了要求(一个例子没有做一个规范),但是如果我们假设第一个源文档正好包含一个 /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 相比,它仍然会少很多代码。

【讨论】:

  • 源和目标可以有多个/Root/folders/folder 我想从源中选择(带有指定的标题)并将其与目标中的任何内容合并。如果目的地已经有内容,则不得覆盖;必须添加源内容。在上面的示例中,结果将包含一个 &lt;folder caption="TestBlock" description="desc" moniker="" /&gt; 和多个 &lt;folders&gt;
  • 那么请用更完整的问题规范更新您的问题,并将您的测试示例更新为 (a) 提供更大的需求覆盖率和 (b) 删除一些不相关的细节。
猜你喜欢
  • 2010-10-13
  • 2013-05-15
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 2021-04-29
相关资源
最近更新 更多