首页 > 解决方案 > 根据映射条件合并 XML

问题描述

我正在寻找一种满足某些映射条件的合并 XML 的最佳方法

XML1:

  <root>
        <key>123<key>
  </root>

XML2:

  <root>
       <base_node_1>
           <key>123<key>
           <data1>aaa</data1>
           <data2>bbb</data2>
       </base_node_1>
       <base_node_2>
           <key>456<key>
           <data1>xxx</data1>
           <data2>yyy</data2>
       </base_node_2>
  </root>

预期输出:

<root>
        <key>123<key>
        <data1>aaa</data1>
        <data2>bbb</data2>
  </root>

将 XML1 中的 'key' 匹配到 XML2 中的块。如果找到匹配,则将属性映射到最终输出 xml。

这里要注意的是 XML2 标签中的 'base_node' 可能会改变。大约有 100 个可能的标签。

使用 JAXB 将 XML 转换为 Java 对象并将它们映射到 Java 中是一种方法。但是考虑到第二个 xml - XML2 的结构,JAXB 看起来很复杂

有一个更好的方法吗?可能是基于 XPATH 的映射?

标签: xmlxsltxpathjaxb

解决方案


XSLT 2 或 3:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="key-doc">
  <root>
        <key>123</key>
  </root>      
  </xsl:param>
  
  <xsl:key name="lookup" match="root/key" use="."/>

  <xsl:output indent="yes"/>
  
  <xsl:template match="/*">
      <xsl:copy>
          <xsl:copy-of select="*[key('lookup', key, $key-doc)]/*"/>
      </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

第一个文档是为了示例的自包含而内联的,但当然可以声明为<xsl:param name="key-doc" select="doc('xml1.xml')"/>

即使在 XSLT 1 中,不使用键并使用例如<xsl:param name="key-doc" select="document('xml1.xml')"/>,您也可以简单地选择

  <xsl:template match="/*">
      <xsl:copy>
          <xsl:copy-of select="*[key = $key-doc/root/key]/*"/>
      </xsl:copy>
  </xsl:template>

找到匹配的元素并将其子元素复制到输出。


推荐阅读