user1906222
user1906222

Reputation: 77

generating multiple xml file using xslt

i am trying to generate multiple xml file using xslt. my *input.xm*l file is

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"     
<soapenv:Body>
 <ns1:getDocumentByKeyResponse   soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <Document xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
<Attributes>
 <Attribute name="duration">0:00:00.084</Attribute>
 <Attribute name="count">7</Attribute>
<Attribute name="entity">Requisition</Attribute>
<Attribute name="mode">XML</Attribute>
<Attribute name="version">http://www.taleo.com/ws/tee800/2009/01</Attribute>
</Attributes>
<Content>
<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <record>
<field name="ContestNumber">1300000F</field>
  <field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000H</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000T</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000018</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">000123</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000R</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000016</field>
 <field name="ManagerRequisitionTitle">Project Manager</field>
 </record>
</ExportXML>
</Content>
</Document>
</ns1:getDocumentByKeyResponse>
</soapenv:Body>
</soapenv:Envelope>

my xslt is sample.xslt

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pDest" select="'file:///c:/temp/'"/>
<xsl:template match="*[starts-with(name(),'ExportXML')]">
<xsl:for-each select="record">
<xsl:result-document href="{$pDest}section{position()}.xml">
<JobPositionPostings>
<JobPositionPosting>
<xsl:apply-templates select="*:field[starts-with(@name,'ContestNumber')]"/>
 <JobDisplayOptions>
 <xsl:apply-templates select="*:field[starts-with(@name,'ManagerRequisitionTitle')]"/>
 </JobDisplayOptions>
</JobPositionPosting>
</JobPositionPostings>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

i am not getting proper output. i want that every input tag data comes in separate file like this

  <?xml version="1.0" encoding="UTF-8"?>
  </JobPositionPostings>
  <JobPositionPostings>
  <JobPositionPosting>
 <contestnumber>13000016</contestnumber>
 <JobDisplayOptions>
 <managerrequisitiontitle>Project Manager</managerrequisitiontitle>
 </JobDisplayOptions>
 </JobPositionPosting>
 </JobPositionPostings>

please suggest me any solution.thanks in advance.

Upvotes: 2

Views: 2585

Answers (2)

Tim C
Tim C

Reputation: 70598

You've got a couple of problems with your XSLT, mainly around namespaces. You start off with the following template match

<xsl:template match="*[starts-with(name(),'ExportXML')]">

This is fine, but you only really need to do this if you know the ExportXML element belongs to a namespace (which in your case it does), but do not what the namespace will be. Ideally though, you should be using "local-name()" here though, not "name()" because name() will include any namespace prefix, and so would not work in the following case.

<x:ExportXML xmlns:x="http://www.taleo.com/ws/integration/toolkit/2005/07">

Anyway, the problem occurs with your next line of XSLT

<xsl:for-each select="record">

This is looking for a record element not part of any namespace, when the record element in your XML is part of the same namespace as ExportXML (as are all its descendants). You should be using the similar syntax here (assuming you genuinely don't know the namespace in advance)

<xsl:for-each select="*[starts-with(local-name(),'record')]">

The next problem is with the code you use to get the value of "ContestNumber" (and "ManagerRequisitionTitle"):

<xsl:apply-templates select="*:field[starts-with(@name,'ContestNumber')]"/>

Aside from being syntactically invalid, you also have the same issue with the field element being in the namespace too, so you need to do this

<xsl:apply-templates select="*[starts-with(local-name(), 'field')][@name='ContestNumber']"/>

Although using xsl:apply-templates is probably not needed here, so xsl:value-of should do.

Try this XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>
   <xsl:param name="pDest" select="'file:///c:/temp/'"/>
   <xsl:template match="*[starts-with(local-name(),'ExportXML')]">
      <xsl:for-each select="*[starts-with(local-name(),'record')]">
         <xsl:result-document href="{$pDest}section{position()}.xml">
            <JobPositionPostings>
               <JobPositionPosting>
                  <xsl:value-of select="*[starts-with(local-name(), 'field')][@name='ContestNumber']"/>
                  <JobDisplayOptions>
                     <xsl:value-of select="*[starts-with(local-name(), 'field')][@name='ManagerRequisitionTitle']"/>
                  </JobDisplayOptions>
               </JobPositionPosting>
            </JobPositionPostings>
         </xsl:result-document>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="*[starts-with(local-name(), 'Attributes')]"/>
</xsl:stylesheet>

Do also note the template to match, and ignore Attributes because otherwise XSLT's built-in templates will match these, and output the text value.

Of course, if you did now that the namespace was always going to be the same, you could simplify your XSLT by declaring the namespace. This XSLT should also work:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07">
   <xsl:output omit-xml-declaration="yes" indent="yes"/>
   <xsl:strip-space elements="*"/>
   <xsl:param name="pDest" select="'file:///c:/temp/'"/>
   <xsl:template match="ExportXML">
      <xsl:for-each select="record">
         <xsl:result-document href="{$pDest}section{position()}.xml">
            <JobPositionPostings>
               <JobPositionPosting>
                  <xsl:value-of select="field[@name='ContestNumber']"/>
                  <JobDisplayOptions>
                     <xsl:value-of select="field[@name='ManagerRequisitionTitle']"/>
                  </JobDisplayOptions>
               </JobPositionPosting>
            </JobPositionPostings>
         </xsl:result-document>
      </xsl:for-each>
   </xsl:template>
   <xsl:template match="Attributes"/>
</xsl:stylesheet>

EDIT: One way to test the template is matching is to temporarily change the XSLT to not use xsl:result-document. Instead, change it to output a normal element at this point

<!-- <xsl:result-document href="{$pDest}section{position()}.xml"> -->
<file href="{$pDest}section{position()}.xml">
   <JobPositionPostings>...</JobPositionPostings>
</file>

Then, use an XSLT testing tool (such as http://xslttest.appspot.com/) and test your XML and amended XSLT, to see if multiple file elements are being created. If so, you should be able to change back to using xsl:result-document.

Upvotes: 0

G. Ken Holman
G. Ken Holman

Reputation: 4393

Two solutions are below, though I had to make some assumptions because you are not clear on your requirements. The first solution soap.xsl uses the pull style where elements are manifest in your stylesheet. The second solution soap2.xsl uses the push style where elements are synthesized from the attribute names. I didn't know what more you wanted to do with your stylesheet after these basics were covered.

t:\ftemp>type soap.xml 
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">     
<soapenv:Body>
 <ns1:getDocumentByKeyResponse   soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"   xmlns:ns1="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <Document xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
<Attributes>
 <Attribute name="duration">0:00:00.084</Attribute>
 <Attribute name="count">7</Attribute>
<Attribute name="entity">Requisition</Attribute>
<Attribute name="mode">XML</Attribute>
<Attribute name="version">http://www.taleo.com/ws/tee800/2009/01</Attribute>
</Attributes>
<Content>
<ExportXML xmlns="http://www.taleo.com/ws/integration/toolkit/2005/07">
 <record>
<field name="ContestNumber">1300000F</field>
  <field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000H</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000T</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000018</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">000123</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">1300000R</field>
<field name="ManagerRequisitionTitle">Project Manager</field>
</record>
<record>
<field name="ContestNumber">13000016</field>
 <field name="ManagerRequisitionTitle">Project Manager</field>
 </record>
</ExportXML>
</Content>
</Document>
</ns1:getDocumentByKeyResponse>
</soapenv:Body>
</soapenv:Envelope>
t:\ftemp>rmdir /s /q temp 

t:\ftemp>call xslt2 soap.xml soap.xsl 

t:\ftemp>type temp\section1.xml 
<JobPositionPostings>
   <JobPositionPosting>
      <contestnumber>1300000F</contestnumber>
      <JobDisplayOptions>
         <managerrequisitiontitle>Project Manager</managerrequisitiontitle>
      </JobDisplayOptions>
   </JobPositionPosting>
</JobPositionPostings>

t:\ftemp>dir temp 
 Volume in drive T is VBOX_t
 Volume Serial Number is 0E00-0001

 Directory of t:\ftemp\temp

2013-08-11  17:00               269 section1.xml
2013-08-11  17:00               269 section2.xml
2013-08-11  17:00               269 section3.xml
2013-08-11  17:00               269 section4.xml
2013-08-11  17:00               267 section5.xml
2013-08-11  17:00               269 section6.xml
2013-08-11  17:00               269 section7.xml
               7 File(s)          1,881 bytes
               0 Dir(s)   8,351,150,080 bytes free

t:\ftemp>type soap.xsl 
<xsl:stylesheet version="2.0"
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:param name="pDest" select="'temp/'"/>

<xsl:template match="/">
  <xsl:for-each select="//record">
    <xsl:result-document href="{$pDest}section{position()}.xml">
      <JobPositionPostings>
        <JobPositionPosting>
          <contestnumber>
            <xsl:value-of select="field[@name='ContestNumber']"/>
          </contestnumber>
          <JobDisplayOptions>
            <managerrequisitiontitle>
              <xsl:value-of select="field[@name='ManagerRequisitionTitle']"/>
            </managerrequisitiontitle>
          </JobDisplayOptions>
        </JobPositionPosting>
      </JobPositionPostings>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rmdir /s /q temp 

t:\ftemp>call xslt2 soap.xml soap2.xsl 

t:\ftemp>type temp\section2.xml 
<JobPositionPostings>
   <JobPositionPosting>
      <contestnumber>1300000H</contestnumber>
      <JobDisplayOptions>
         <managerrequisitiontitle>Project Manager</managerrequisitiontitle>
      </JobDisplayOptions>
   </JobPositionPosting>
</JobPositionPostings>

t:\ftemp>dir temp 
 Volume in drive T is VBOX_t
 Volume Serial Number is 0E00-0001

 Directory of t:\ftemp\temp

2013-08-11  17:00               269 section1.xml
2013-08-11  17:00               269 section2.xml
2013-08-11  17:00               269 section3.xml
2013-08-11  17:00               269 section4.xml
2013-08-11  17:00               267 section5.xml
2013-08-11  17:00               269 section6.xml
2013-08-11  17:00               269 section7.xml
               7 File(s)          1,881 bytes
               0 Dir(s)   8,351,670,272 bytes free

t:\ftemp>type soap2.xsl 
<xsl:stylesheet version="2.0" 
  xpath-default-namespace="http://www.taleo.com/ws/integration/toolkit/2005/07"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:param name="pDest" select="'temp/'"/>

<xsl:template match="/">
  <xsl:for-each select="//record">
    <xsl:result-document href="{$pDest}section{position()}.xml">
      <JobPositionPostings>
        <JobPositionPosting>
          <xsl:apply-templates select="field[@name='ContestNumber']"/>
          <JobDisplayOptions>
            <xsl:apply-templates
                     select="field[@name='ManagerRequisitionTitle']"/>
          </JobDisplayOptions>
        </JobPositionPosting>
      </JobPositionPostings>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

<xsl:template match="field">
  <xsl:element name="{lower-case(@name)}">
    <xsl:value-of select="."/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done! 

Upvotes: 1

Related Questions