如何使用 java xslt 将数据从一个 xml 文件复制到另一个文件

how to copy data from one xml files in to another using java xslt

  1. 我需要全部更换吗?在 file1.xml 中,元素值存在于 File2.xml.
  2. 并且还需要删除 File1.xml 中存在的额外元素节点,其值不存在于 File2.xml 中。 (即在我的示例输入中,需要从 file1.xml 中删除 totalDueWithoutTax 元素,因为它不存在于 File2.xml.
  3. 可能有这样的情况,我们在 File2 中有多个元素,但在 File1 中只有一个对应的元素。就像在我下面的示例中一样,我们在 File2 中有两个 salesInfo 元素,但在 File1 中我们只有一个。在这种情况下,作为预期输出,我们需要 File2.
  4. salesInfo 元素
  5. 这只是示例输入。在实际场景中,输入的 xml 可能不同,这意味着我们每次都可以获得不同格式的 xml。

请在 java 中建议我如何做到这一点。如果能用xslt实现就更好了。

        **File 1 -- input xml**
       <order>
            <orderId>?</orderId>
             <sales>
              <salesInfo>
                <salesChannel>?</salesChannel>
                <senderSystemId>?</senderSystemId>
                <applicationId>?</applicationId>
                <totalDueWithoutTax>?</totalDueWithoutTax>
              </salesInfo>
              <salesid>?</salesid>
           </sales>
        </order>
        
        **File 2 -- input xml**
    
        <order>
          <orderId>4567</orderId>
          <sales>
              <salesInfo>
                <salesChannel>abc</salesChannel>
                <senderSystemId>def</senderSystemId>
                <applicationId>123</applicationId>
                <esignatureCaptureMode>INLINE</esignatureCaptureMode>
              </salesInfo>
              <salesInfo>
                <salesChannel>xyz</salesChannel>
                <senderSystemId>uvw</senderSystemId>
                <applicationId>234</applicationId>
                <esignatureCaptureMode>outline</esignatureCaptureMode>
              </salesInfo>
              <salesid>789</salesid>
        </sales>
        </order>
        
        **Expected output:**
        
        <order>
            <orderId>4567</orderId>
            <sales>
              <salesInfo>
                <salesChannel>abc</salesChannel>
                <senderSystemId>def</senderSystemId>
                <applicationId>123</applicationId>
              </salesInfo>
              <salesInfo>
               <salesChannel>xyz</salesChannel>
                <senderSystemId>uvw</senderSystemId>
                <applicationId>234</applicationId>
              </salesInfo>
              <salesid>789</salesid>
          </sales>
        </order>

你可以考虑一个group/merge问题:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="#all"
  xmlns:mf="http://example.com/mf"
  expand-text="yes">
  
  <xsl:param name="doc2" select="doc('file2.xml')"/>>

  <xsl:output method="xml" indent="yes"/>
  
  <xsl:function name="mf:merge" as="node()*">
    <xsl:param name="nodes1" as="node()*"/>
    <xsl:param name="nodes2" as="node()*"/>
    <xsl:for-each-group select="$nodes1, $nodes2" group-by="node-name()">
      <xsl:choose>
        <xsl:when test="not(*) and . = '?' and current-group()[2]">
          <xsl:apply-templates select="current-group()[2]"/>
        </xsl:when>
        <xsl:when test="current-group()[1][*] and current-group()[2][*]">
          <xsl:copy>
            <xsl:sequence select="mf:merge(*, current-group()[2]/*)"/>
          </xsl:copy>
        </xsl:when>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:function>
  
  <xsl:template match="/*">
    <xsl:copy>
      <xsl:sequence select="mf:merge(*, $doc2/*/*)"/>
    </xsl:copy>
  </xsl:template>
    
  <xsl:mode on-no-match="shallow-copy"/>

</xsl:stylesheet>

根据结构或合并要求,使用 xsl:for-each-group select="$nodes1, $nodes2" group-by="path(.)" 而不是 <xsl:for-each-group select="$nodes1, $nodes2" group-by="node-name()"> 可能更合适,例如,如果一个元素可以有多个同名的子元素。

一个“开箱即用”的建议:您可能希望将 file1 视为代表一种小型模板语言。如果您这样想,那么想到的一个选择是将您的小模板语言翻译成 XSLT(当然,可以使用 XSLT 完成的翻译)。

所以你的转换会转换

<salesChannel>?</salesChannel>

<salesChannel>
      <xsl:value-of select="order/salesinfo/saleschannel"/>
</salesChannel>

其中select属性中的表达式是通过调用path()获得的。

这种方法的优点是您可以开始发展您的“小模板语言”以包含额外的功能,如出现要求时的循环和条件。