我有两个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>
任何帮助(请菜鸟级别)都将不胜感激。
答案 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进行操作相比,代码仍然要少得多。