0

I want to split the xml into multiple xml but some common elements have to be present in all the splitted xml.

Input

<xmlroot>
<FileDetails>
   <Filename>test.xml</FileName>
   <FileDate>10312014</FileDate>
</FileDetails>
 <FileInfo>
   <Test>Hello1</Test>
 </FileInfo>
 <FileInfo>
    <Test>Hello2</Test>
 </FileInfo>
 </xmlroot>

Output1

<xmlroot>
<FileDetails>
   <Filename>test.xml</FileName>
   <FileDate>10312014</FileDate>
</FileDetails>
 <FileInfo>
    <Test>Hello1</Test>
 </FileInfo>
</xmlroot>

output2

<xmlroot>
<FileDetails>
   <Filename>test.xml</FileName>
   <FileDate>10312014</FileDate>
</FileDetails>
 <FileInfo>
    <Test>Hello2</Test>
 </FileInfo>
 </xmlroot>
SatishA
  • 1
  • 1

1 Answers1

0

Assuming XSLT 2.0

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="/">
  <xsl:apply-templates select="*/FileInfo"/>
</xsl:template>

<xsl:template match="*/FileInfo">
  <xsl:result-document href="Output{position()}.xml">
    <xsl:apply-templates select="/*" mode="split">
      <xsl:with-param name="target" tunnel="yes" select="current()"/>
    </xsl:apply-templates>
  </xsl:result-document>
</xsl:template>

<xsl:template match="@* | node()" mode="#all">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()" mode="#current"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*/FileInfo" mode="split">
  <xsl:param name="target" tunnel="yes"/>
  <xsl:if test="$target is .">
    <xsl:next-match/>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

If you need a solution with Xalan Java in XSLT 1.0 but making use of a Xalan specific extension element then here is an example:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:redirect="http://xml.apache.org/xalan/redirect"
  extension-element-prefixes="redirect"
  exclude-result-prefixes="redirect"
  version="1.0">

<xsl:output indent="yes"/>

<xsl:template match="/">
  <xsl:apply-templates select="*/FileInfo" mode="split"/>
</xsl:template>

<xsl:template match="*/FileInfo" mode="split">
  <redirect:write file="OutputXalanTest{position()}.xml">
    <xsl:apply-templates select="/*">
      <xsl:with-param name="target" select="current()"/>
    </xsl:apply-templates>
  </redirect:write>
</xsl:template>

<xsl:template match="@* | node()" name="identity">
  <xsl:param name="target"/>
  <xsl:copy>
    <xsl:apply-templates select="@* | node()">
      <xsl:with-param name="target" select="$target"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="*/FileInfo">
  <xsl:param name="target"/>
  <xsl:if test="generate-id($target) = generate-id(.)">
    <xsl:call-template name="identity"/>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

I have only tested that with the Xalan version available from Apache but hopefully it works as well with the Xalan version Sun/Oracle incorporated in the Java JRE.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • I am seeing the below error, javax.xml.transform.TransformerConfigurationException: javax.xml.transform.TransformerException: org.xml.sax.SAXException: Illegal value: #all used for QNAME attribute: mode – SatishA Oct 31 '14 at 18:26
  • It is an XSLT 2.0 stylesheet supposed to be used with an XSLT 2.0 processor like Saxon 9 from http://saxon.sourceforge.net/. The XSLT processor in the Sun/Oracle JRE only supports XSLT 1.0. – Martin Honnen Oct 31 '14 at 18:29