Sort XML File using XSLT -


i sorting xml file using xslt , facing small problem here..

my xml file given below:

<?xml version="1.0" encoding="iso-8859-1"?>     <bulkcmconfigdatafile xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="a.xsd a.xsd">     <fileheader fileformatversion="32.615 v5.0"/>     <configdata dnprefix="" log="0" mediation="false">     <subs:sumsubscriberprofile id="378466">     <subs:sumsubscriptionprofile id="1">     <subs:imsserviceprofile id="1" modifier="create">     <subs:attributes>     <subs:chargingidx>1</subs:chargingidx>     </subs:attributes>     </subs:imsserviceprofile>     </subs:sumsubscriptionprofile>     </subs:sumsubscriberprofile>     <subs:sumsubscriberprofile id="378460">     <subs:sumsubscriptionprofile id="1">     <subs:imsserviceprofile id="1" modifier="create">     <subs:attributes>     <subs:chargingidx>2</subs:chargingidx>     </subs:attributes>     </subs:imsserviceprofile>     </subs:sumsubscriptionprofile>     </subs:sumsubscriberprofile>     </configdata>     <filefooter datetime="2015-03-14t10:10:10"/>     </bulkcmconfigdatafile> 

and using following style sheet:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0"     xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns="a.xsd"     xmlns:xn="b.xsd" xmlns:subs="c.xsd">     <xsl:output method="xml" indent="yes" version="1.0"         encoding="iso-8859-1" />     <xsl:strip-space elements="*" />      <xsl:param name="outermatchelement" />     <xsl:param name="innermatchelement" />     <xsl:param name="sortby" />       <xsl:template match="@*|node()">         <xsl:copy>             <xsl:apply-templates select="@*|node()" />         </xsl:copy>     </xsl:template>     <xsl:template match="*[name()=$outermatchelement]">         <xsl:copy>             <xsl:copy-of select="@*" />             <xsl:choose>                 <xsl:when test="count(*[name()=$innermatchelement]) = 0">                     <xsl:apply-templates select="*[name()=$sortby]">                         <xsl:sort select="@id" data-type="number" />                     </xsl:apply-templates>                 </xsl:when>                 <xsl:when test="count(*[name()=$innermatchelement]) = 1">                     <xsl:apply-templates select="*[name()=$innermatchelement]/*[name()=$sortby]">                         <xsl:sort select="@id" data-type="number" />                     </xsl:apply-templates>                 </xsl:when>                 <xsl:otherwise>                     <xsl:apply-templates select="*[name()=$innermatchelement]">                         <xsl:sort select="*[name()=$sortby]/@id" data-type="number" />                     </xsl:apply-templates>                 </xsl:otherwise>             </xsl:choose>         </xsl:copy>     </xsl:template> </xsl:stylesheet> 

where outermatchelement = bulkcmconfigdatafile, innermatchelement=configdata , sortby=subs:sumsubscriberprofile

i getting following result using stylesheet:

<?xml version="1.0" encoding="iso-8859-1"?><bulkcmconfigdatafile xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="configdata.xsd configdata.xsd">     <subs:sumsubscriberprofile id="378460">     <subs:sumsubscriptionprofile id="1">     <subs:imsserviceprofile id="1" modifier="create">     <subs:attributes>     <subs:chargingidx>2</subs:chargingidx>     </subs:attributes>     </subs:imsserviceprofile>     </subs:sumsubscriptionprofile>     </subs:sumsubscriberprofile>     <subs:sumsubscriberprofile id="378466">     <subs:sumsubscriptionprofile id="1">     <subs:imsserviceprofile id="1" modifier="create">     <subs:attributes>     <subs:chargingidx>1</subs:chargingidx>     </subs:attributes>     </subs:imsserviceprofile>     </subs:sumsubscriptionprofile>     </subs:sumsubscriberprofile>     </bulkcmconfigdatafile> 

expected output following:

<?xml version="1.0" encoding="iso-8859-1"?>         <bulkcmconfigdatafile xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd"      xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="configdata.xsd configdata.xsd">         <fileheader fileformatversion="32.615 v5.0"/>         <configdata dnprefix="" log="0" mediation="false">         <subs:sumsubscriberprofile id="378460">         <subs:sumsubscriptionprofile id="1">         <subs:imsserviceprofile id="1" modifier="create">         <subs:attributes>         <subs:chargingidx>2</subs:chargingidx>         </subs:attributes>         </subs:imsserviceprofile>         </subs:sumsubscriptionprofile>         </subs:sumsubscriberprofile>         <subs:sumsubscriberprofile id="378466">         <subs:sumsubscriptionprofile id="1">         <subs:imsserviceprofile id="1" modifier="create">         <subs:attributes>         <subs:chargingidx>1</subs:chargingidx>         </subs:attributes>         </subs:imsserviceprofile>         </subs:sumsubscriptionprofile>         </subs:sumsubscriberprofile>         </configdata>         <filefooter datetime="2015-03-14t10:10:10"/>         </bulkcmconfigdatafile> 

you notice difference file header , file footer tags missing in output getting, please guide me how resolve issue?i trying make sorting process generic xml files.

in given input sample have 1 element matching $innermatchelement variable, second xsl:when applies. however, in relevant block of code gets executed in case, selecting child elements of "innermatchelement" element, other children ignored.

try changing second xsl:when instead.

<xsl:when test="count(*[name()=$innermatchelement]) = 1">    <xsl:apply-templates select="*[following-sibling::*[name()=$innermatchelement]]" />    <xsl:apply-templates select="*[name()=$innermatchelement]/*[name()=$sortby]">       <xsl:sort select="@id" data-type="number" />     </xsl:apply-templates>     <xsl:apply-templates select="*[preceding-sibling::*[name()=$innermatchelement]]" /> </xsl:when> 

so, select elements occur before "innermatchelement" elements, select inner match one, , select elements occur after it.

you may have add similar lines other 2 conditions.

note, if want "innermatchelement" tag too, can achieve creating new 1 xsl:element

<xsl:when test="count(*[name()=$innermatchelement]) = 1">    <xsl:apply-templates select="*[following-sibling::*[name()=$innermatchelement]]" />    <xsl:element name="{$innermatchelement}">       <xsl:apply-templates select="*[name()=$innermatchelement]/@*" />       <xsl:apply-templates select="*[name()=$innermatchelement]/*[name()=$sortby]">          <xsl:sort select="@id" data-type="number" />       </xsl:apply-templates>   </xsl:element>   <xsl:apply-templates select="*[preceding-sibling::*[name()=$innermatchelement]]" /> </xsl:when> 

alternatively, make better use of template matching. try xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform" xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd">     <xsl:output method="xml" indent="yes" version="1.0" encoding="iso-8859-1" />     <xsl:strip-space elements="*" />      <xsl:param name="outermatchelement" select="'bulkcmconfigdatafile'" />     <xsl:param name="innermatchelement" select="'configdata'" />     <xsl:param name="sortby" select="'subs:sumsubscriberprofile'" />      <xsl:template match="@*|node()">         <xsl:copy>             <xsl:apply-templates select="@*|node()" />         </xsl:copy>     </xsl:template>      <xsl:template match="*[name()=$outermatchelement]">         <xsl:copy>             <xsl:copy-of select="@*" />             <xsl:choose>                 <xsl:when test="count(*[name()=$innermatchelement]) = 0">                     <xsl:apply-templates select="*[name()=$sortby]">                         <xsl:sort select="@id" data-type="number" />                     </xsl:apply-templates>                 </xsl:when>                 <xsl:when test="count(*[name()=$innermatchelement]) = 1">                     <xsl:apply-templates select="*[name()=$innermatchelement]" mode="single" />                 </xsl:when>                 <xsl:otherwise>                     <xsl:apply-templates select="*[name()=$innermatchelement]">                         <xsl:sort select="*[name()=$sortby]/@id" data-type="number" />                     </xsl:apply-templates>                 </xsl:otherwise>             </xsl:choose>         </xsl:copy>     </xsl:template>      <xsl:template match="*[name()=$innermatchelement]" mode="single">         <xsl:apply-templates select="preceding-sibling::*" />         <xsl:copy>             <xsl:apply-templates select="@*" />             <xsl:apply-templates select="*[name()=$sortby]">                 <xsl:sort select="@id" data-type="number" />              </xsl:apply-templates>         </xsl:copy>         <xsl:apply-templates select="following-sibling::*" />     </xsl:template> </xsl:stylesheet> 

as aside, error in xslt 1.0 have variable in template match (see http://www.w3.org/tr/xslt#section-defining-template-rules), should fail

<xsl:template match="*[name()=$outermatchelement]"> 

however, xslt 1.0 allow it, possibly in case. if switch processor gets error, solution this...

<xsl:template match="*">     <xsl:choose>         <xsl:when test="name()=$outermatchelement">             <!-- existing code -->         </xsl:when>         <xsl:otherwise>            <!-- identity template -->         </xsl:otherwise>    </xsl:choose> </xsl:template> 

Comments

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -