Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
XML
data.xmlanalysis
mappoint.webservice
msf
msxml-webrelease
netmyservices.sdk
passport.sdk
soap
soapsdk
uddi.general
uddi.programming
uddi.specification
xml
xmlsqlwebrelease
xsl
  
 
date: Fri, 18 Apr 2008 18:20:30 +0200,    group: microsoft.public.xml        back       


help needed with namespace and clonenode   
Hi,

I need a bit of help preventing empty namespaces littering my xml 
output.
The goal of the routine is to concatenate seperate xml-files (or rather 
parts of) into one.

With CloneNode, copying node from the input xml-file to an output is 
easy. But empty xmlns-tags are added. These I need to avoid

I'm extremely new at xml, so be gentle on the following sample code.

best regards
glenn

-----Input-----
<VATSENDING xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<VATRECORD>
		<RECNUM>001</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
</VATSENDING>
---------------
-----Output----
<VATSENDING xmlns="http://www.w3.org/2001/XMLSchema-instance">
	<VATRECORD xmlns="">             <<<<---- xmlns="" these offend
		<RECNUM>001</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
	<VATRECORD xmlns="">             <<<<---- xmlns="" these offend
		<RECNUM>002</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
	<VATRECORD xmlns="">             <<<<---- xmlns="" these offend
		<RECNUM>003</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
</VATSENDING>
---------------

-----
Sub testxml()

Dim o_XML_In As MSXML2.DOMDocument
Dim o_XML_Out As MSXML2.DOMDocument
Dim o_root As MSXML2.IXMLDOMElement
Dim o_XML_Elt As MSXML2.IXMLDOMElement
Dim o_XML_copy As MSXML2.IXMLDOMElement

Dim n_CNTID As Long

    Set o_XML_In = New MSXML2.DOMDocument
    With o_XML_In
        .async = False
        .validateOnParse = False
        .Load "in.xml"
    End With

'Element to duplicate
    Set o_XML_Elt = o_XML_In.documentElement.selectSingleNode
("VATRECORD")
    
'output file
    Set o_XML_Out = New MSXML2.DOMDocument
    With o_XML_Out
        .async = False
        .validateOnParse = False
    End With

'Create root element in output file
    Set o_root = o_XML_Out.createNode(1, "VATSENDING", 
"http://www.w3.org/2001/XMLSchema-instance")
    o_XML_Out.appendChild o_root

    Set o_root = o_XML_Out.documentElement
    
'as test, duplicate node a few times, but modify counter
    n_CNTID = 1
    While n_CNTID < 4
    
            Set o_XML_copy = o_XML_Elt.cloneNode(True)
            o_XML_copy.childNodes.Item(0).nodeTypedValue = Format
(n_CNTID, "000")
            
            o_root.appendChild o_XML_copy
                        
            n_CNTID = n_CNTID + 1
    Wend
    o_XML_Out.Save "out.xml"
End Sub
-----
date: Fri, 18 Apr 2008 18:20:30 +0200   author:   glenn

Re: help needed with namespace and clonenode   
glenn wrote:

> <VATSENDING xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> 	<VATRECORD>
> 		<RECNUM>001</RECNUM>
> 		<VATNUMBER>123456002</VATNUMBER>
> 	</VATRECORD>
> </VATSENDING>

So the above XML document has four elements named 'VATSENDING', 
'VATRECORD', 'RECNUM', 'VATNUMBER' which are all in _no namespace_.


> <VATSENDING xmlns="http://www.w3.org/2001/XMLSchema-instance">

This document has a root element named 'VATSENDING' in the namespace 
http://www.w3.org/2001/XMLSchema-instance. (I don't know why you use a 
namespace defined by the W3C for your elements but that is not the issue).
If you try to move elements from the first document to the second then 
they are not changed in any way, they keep their local name and their 
namespace URI. That way the serializer has to add the xmlns="" attribute 
  you complain about below:

> 	<VATRECORD xmlns="">             <<<<---- xmlns="" these offend

The solution to the problem is not to clone the nodes but rather to 
transform them to the new target namespace. An XSLT stylesheet can do 
that: assuming the XML input is

<VATSENDING xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<VATRECORD>
		<RECNUM>001</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
</VATSENDING>

and you want to transform that to e.g.

<VATSENDING xmlns="http://example.com/ns1" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<VATRECORD xmlns="">
		<RECNUM>001</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
	<VATRECORD xmlns="">
		<RECNUM>002</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
	<VATRECORD xmlns="">
		<RECNUM>003</RECNUM>
		<VATNUMBER>123456002</VATNUMBER>
	</VATRECORD>
</VATSENDING>

then the following stylesheet does that:

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

   <xsl:param name="target-namespace" select="'http://example.com/ns1'"/>
   <xsl:param name="record-count" select="4"/>

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="VATSENDING">
     <xsl:element name="{local-name()}" namespace="{$target-namespace}">
       <xsl:copy-of select="namespace::*"/>
       <xsl:call-template name="make-records">
         <xsl:with-param name="rec" select="VATRECORD"/>
         <xsl:with-param name="n" select="$record-count"/>
       </xsl:call-template>
     </xsl:element>
   </xsl:template>

   <xsl:template name="make-records">
     <xsl:param name="rec"/>
     <xsl:param name="n"/>
     <xsl:if test="$n > 0">
       <xsl:element name="{local-name($rec)}" 
namespace="{$target-namespace}">
         <xsl:element name="RECNUM" namespace="{$target-namespace}">
           <xsl:value-of select="format-number($record-count - $n + 1, 
'000')"/>
         </xsl:element>
         <xsl:element name="VATNUMBER" namespace="{$target-namespace}">
           <xsl:value-of select="$rec/VATNUMBER"/>
         </xsl:element>
       </xsl:element>
       <xsl:call-template name="make-records">
         <xsl:with-param name="rec" select="$rec"/>
         <xsl:with-param name="n" select="$n - 1"/>
       </xsl:call-template>
     </xsl:if>
   </xsl:template>

</xsl:stylesheet>

You can run XSLT 1.0 stylesheet with MSXML 3 or later using 
transformNode or transformNodeToObject methods or using XSLTProcesssor.


If you don't want to use XSLT but want to stick with DOM then you need 
to write code that creates new elements in the namespace you want. 
cloneNode does not do what you want to achieve.


-- 

	Martin Honnen --- MVP XML
	http://JavaScript.FAQTs.com/
date: Fri, 18 Apr 2008 18:52:31 +0200   author:   Martin Honnen

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us