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 -----
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/