Search code examples
xmlxsltxsdxslt-1.0xslt-2.0

XSLT to transform value from one file to another file based on sequence


Here are the source files filea.xml & fileb.xml 1. filea.xml Here siteid # 1 in filea.xml refers to the first Site as occurrence in the fileb.xml file for RSA00083. Similarly siteid # 2 in filea.xml refers to the Second Site as occurrence in the fileb.xml file for RSA00034. Similarly partnum # 1 in filea.xml refers to the Second Site as occurrence in the fileb.xml file for 000B96. Similarly partnum # 2 in filea.xml refers to the Second Site as occurrence in the fileb.xml file for 000B97.

 <Json>
 <site_req>
        <siteid>1</siteid>
        <quantityAvail>1</quantityAvail>
        <quantityMax>1</quantityMax>
        <partNum>1</partNumber>
        <partRequested>1</partRequested>
     </FMI_INQUIRE_REQ>
 <site_req>
        <siteid>1</siteid>
        <quantityAvail>2</quantityAvail>
        <quantityMax>2</quantityMax>
        <partNum>2</partNum>
        <partRequested<2</partRequested>
     </site_req>
 <site_req>
        <siteid>2</siteid>
        <quantityAvail>3</quantityAvail>
        <quantityMax>31</quantityMax>
        <partNum>2</partNum>
        <partRequested>3</partRequested>
  </site_req>
  </Json>

2. fileb.xml

  <?xml version="1.0" encoding="UTF-8"?>
- <Json xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     <method>inquire</method>
   - <params>
      - <control>
           <origin>Oracle</origin>
           <version>12.0</version>
        </control>
      - <inquiry>
           <sites>RSA00083</sites>
           <sites>RSA00034</sites>
           <sites>RSA00033</sites>
         - <parts>
              <partnumber>000B96</partnumber>
              <partnumberAssigner>TATA</partnumberAssigner>
              <partnumber>000B97</partnumber>
              <partnumberAssigner>TATA</partnumberAssigner>
           </parts>
        </inquiry>
     </params>
  </Json>

Target File which should be generated through XSLT.

<?xml version="1.0" encoding="utf-8"?>
<result xsi:noNamespaceSchemaLocation="schema.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <siteList>
    <siteid>RSA00083</siteId>
    <partsList>
      <partnum>000B96</partnum>
      <partAssigner>TATA</partAssigner>
      <sequenceNumber>1</sequenceNumber>
      <quantityAvail>202</quantityAvail>
      <quantityMax>163</quantityMax>
    </partsList>
  </siteList>
  <siteList>
    <siteid>RSA00034</siteid>
    <partsList>
       <partnum>000B97</partnum>
      <partAssigner>TATA</partAssigner>
      <sequenceNumber>2</sequenceNumber>
      <quantityAvail>202</quantityAvail>
      <quantityMax>163</quantityMax>
    </partsList>
  </siteList>
  <siteList>
    <siteid>RSA00034</siteid>
    <partsList>
      <sequenceNumber>3</sequenceNumber>
      <quantityAvail>202</quantityAvail>
      <quantityMax>163</quantityMax>
    </partsList>
  </siteList>
  <messages>
    <messageType>INFO</messageType>
    <messageCode>TATA001</messageCode>
    <messageVars></>
    <fieldName />
    <app>Oracle Inventory</app>
    <module>Inv</module>
    <messageText>Information Received.</messageText>
  </messages>
</result>

Need help on generating the XSLT. Here siteid # 1 in filea.xml refers to the first Site as occurrence in the fileb.xml file for RSA00083. Similarly siteid # 2 in filea.xml refers to the Second Site as occurrence in the fileb.xml file for RSA00034. Similarly partnum # 1 in filea.xml refers to the Second Site as occurrence in the fileb.xml file for 000B96. Similarly partnum # 2 in filea.xml refers to the Second Site as occurrence in the fileb.xml file for 000B97. Parts should be grouped by Site and Parts should be sequenced. Thanks in advance.

I am new to XML & XSLT. Just tried little bit. But to process through loop with filea.xml and fileb.xml, need your help and suggestions.

<?xml version="1.0" encoding="UTF-8"?>
 <!-- copy input to change the tagname/elementname -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="site_req/siteid">
        <siteId><xsl:apply-templates select="@*|node()" /></siteid>
    </xsl:template>
    <xsl:template match="site_req/siteid">
        <quantityAvail><xsl:apply-templates select="@*|node()" /></quantityAvail>
    </xsl:template>
        <xsl:template match="site_req/quantityMax">
        <quantityMax><xsl:apply-templates select="@*|node()" /></quantityMax>
    </xsl:template>
        <xsl:template match="site_req/partnum">
        <partnum><xsl:apply-templates select="@*|node()" /></partnum>
    </xsl:template>
     <xsl:template match="site_req/partRequested">
        <partRequested><xsl:apply-templates select="@*|node()" /></partRequested>
      </xsl:template>
</xsl:stylesheet>

Solution

  • Here is something you could use as a starting point for your XSLT. It shows only how to lookup the corresponding values for siteId and partnum from the fileb.xml document, based on their position.

    First, we must have a well-formed XML input (yours is not):

    <Json>
      <site_req>
        <siteid>1</siteid>
        <quantityAvail>1</quantityAvail>
        <quantityMax>1</quantityMax>
        <partNum>1</partNum>
        <partRequested>1</partRequested>
      </site_req>
      <site_req>
        <siteid>1</siteid>
        <quantityAvail>2</quantityAvail>
        <quantityMax>2</quantityMax>
        <partNum>2</partNum>
        <partRequested>2</partRequested>
      </site_req>
      <site_req>
        <siteid>2</siteid>
        <quantityAvail>3</quantityAvail>
        <quantityMax>31</quantityMax>
        <partNum>2</partNum>
        <partRequested>3</partRequested>
      </site_req>
    </Json>
    

    Now we can apply this XSLT:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:variable name="fileB" select="document('fileb.xml')" />
    
    <xsl:template match="/Json">
        <result>
            <xsl:apply-templates select="site_req"/>
        </result>
    </xsl:template>
    
    <xsl:template match="site_req">
        <siteList>
            <siteId>
                <xsl:value-of select="$fileB//sites[position()=current()/siteid]"/>
            </siteId>
            <partsList>
                <partnum>
                    <xsl:value-of select="$fileB//partnumber[position()=current()/partNum]"/>
                </partnum>
            </partsList>
        </siteList>
    </xsl:template>
        
    </xsl:stylesheet>
    

    to get this result:

    <?xml version="1.0" encoding="UTF-8"?>
    <result>
       <siteList>
          <siteId>RSA00083</siteId>
          <partsList>
             <partnum>000B96</partnum>
          </partsList>
       </siteList>
       <siteList>
          <siteId>RSA00083</siteId>
          <partsList>
             <partnum>000B97</partnum>
          </partsList>
       </siteList>
       <siteList>
          <siteId>RSA00034</siteId>
          <partsList>
             <partnum>000B97</partnum>
          </partsList>
       </siteList>
    </result>