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

Time:02-07

  1. I need to replace all ? in file1.xml with element value present in File2.xml.
  2. And also need to remove extra element node present in File1.xml whose value is not present in File2.xml. (i.e. In my sample input need to remove totalDueWithoutTax element from file1.xml as it is not present in File2.xml.
  3. This is just sample input. In real scenario input xmls can be different means we can get different format of xmls everytime.

Please suggest me how to do that in java. It would be better if we can achieve this using xslt.

        **File 1 -- input xml**
       <order>
            <orderId>?</orderId>
          <salesInfo>
            <salesChannel>?</salesChannel>
            <senderSystemId>?</senderSystemId>
            <applicationId>?</applicationId>
            <totalDueWithoutTax>?</totalDueWithoutTax>
          </salesInfo>
        </order>
        
        **File 2 -- input xml**
    
        <order>
          <orderId>4567</orderId>
          <salesInfo>
            <salesChannel>abc</salesChannel>
            <senderSystemId>def</senderSystemId>
            <applicationId>123</applicationId>
            <esignatureCaptureMode>INLINE</esignatureCaptureMode>
          </salesInfo>
        </order>
        
        **Expected output:**
        
        <order>
            <orderId>4567</orderId>
          <salesInfo>
            <salesChannel>abc</salesChannel>
            <senderSystemId>def</senderSystemId>
            <applicationId>123</applicationId>
          </salesInfo>
        </order>

CodePudding user response:

An "out of the box" suggestion: you might like to think of your file1 as representing a little templating language. If you think of it that way, then one option that comes to mind is to translate your little templating language into XSLT (a translation which, of course, can be done using XSLT).

So your transformation would convert

<salesChannel>?</salesChannel>

to

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

where the expression in the select attribute is obtained by calling path().

The advantage of this approach is that you can start to grow your "little templating language" to include extra features, such as loops and conditionals, as the requirements appear.

CodePudding user response:

You could consider a group/merge problem:

<?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>

Depending on the structure or the merging requirements using xsl:for-each-group select="$nodes1, $nodes2" group-by="path(.)" instead of <xsl:for-each-group select="$nodes1, $nodes2" group-by="node-name()"> might be more suitable, for instance if an element can have several child elements of the same name.

  •  Tags:  
  • Related