2
votes

i have xml i want to copy as is like (check xmlns="" and tags. i want to create as is .

The total calculation is taken care. only this issue . it is valid . still client want the expected format to be like that. any help greatly appreciated. three tasks

1)I need to add namespace Employees xmnls="1.2" xmlns:xsi="3" xsi:schemalocation="4"> 2)generating tag like this in the output xml not 3)need to avoid xmlns=""

any help in advance greatly appreciated rameshkumar singh

Input.xml

    <Employees>
            <employee>
             <dept>1</dept>
              <sec></sec>
            </employee>
            <employee>
               <dept>2</dept>
              <sec></sec>
            </employee>
    </Employees>

Expected.XML

         <Employees xmnls="1.2" xmlns:xsi="3" xsi:schemalocation="4">
            <totalemp>2</totalemp>
           <employee>
              <dept>1</dept>
              <sec></sec>
            <employee>
              <employee>
                   <dept>2</dept>
                    <sec></sec>
                 <employee>
              </Employees>


actual.XML
               <Employees>
                    <totalemp>2</totalemp>
                        <employee xmlns="">
                        <dept>1</dept>
                          <sec/>
                        </employee>
                         <employee>
                           <dept>2</dept>
                              <sec/>
                           <employee>
                 </Employees>
2
Can you generate correct XML directly instead of trying to use XSLT to convert? (BTW, your "shift" key seems to be broken as sentences have random capitalization)Alexei Levenkov

2 Answers

3
votes

Here's how you do it:

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

  <xsl:output indent="yes"/>

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

    <xsl:template match="*" priority="2">
        <xsl:element name="{local-name()}" namespace="1.2">
            <xsl:if test="self::Employees">
                <xsl:attribute name="xsi:schemalocation">4</xsl:attribute>          
            </xsl:if>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

You apply the identity transformation as a default and then override it for elements to give them a new namespace as well as a special attribute for the Employees node. I chose to add an if statement but you also can move that logic into another template that matches Employees. I just didn't want to repeat the whole xsl:element thing twice. Matter of taste really.

When I apply this transformation to your input document I end up with:

<Employees xmlns="1.2" xmlns:xsi="3" xsi:schemalocation="4">
    <employee>
        <dept>1</dept>
        <sec/>
    </employee>
    <employee>
        <dept>2</dept>
        <sec/>
    </employee>
</Employees>

You had the xmlns="" in your result likely because you weren't recreating all elements in that new namespace. Also, to be able to add the xsi:schemalocation attribute you need to declare the xsi namespace on the transformation document.

0
votes

This short and simple transformation (has minimum number of templates and doesn't use any explicit XSLT conditional instructions, no xsl:attribute or priority attributes):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xsi="3" xsi:schemalocation="4">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()[not(self::*)]|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*">
  <xsl:element name="{name()}" namespace="1.2">
   <xsl:copy-of select=
   "document('')/*[not(current()/../..)]
                        /@xsi:schemalocation"/>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<Employees>
    <employee>
        <dept>1</dept>
        <sec></sec>
    </employee>
    <employee>
        <dept>2</dept>
        <sec></sec>
    </employee>
</Employees>

produces the wanted, correct result:

<Employees xmlns="1.2" xmlns:xsi="3" xsi:schemalocation="4">
   <employee>
      <dept>1</dept>
      <sec/>
   </employee>
   <employee>
      <dept>2</dept>
      <sec/>
   </employee>
</Employees>