VBA MSXML - Prevent inserting namespace URI into Xpath query result

105 views Asked by At

I am trying to return verbatim text from an MSXML2 node. The XML in question is a KML file with the following structure:

    <?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
    <name>data.kml</name>
    <Folder>
        <name>Temporary Places</name>
        <open>1</open>
        <Placemark>
            <name>Untitled Placemark</name>
            <LookAt>
                <gx:TimeStamp><when>2000</when>
</gx:TimeStamp>
                <longitude>-107.105195493537</longitude>
                <latitude>40.11614841516315</latitude>
                <altitude>0</altitude>
                <heading>0.0484794930795848</heading>
                <tilt>0</tilt>
                <range>209596.4338269165</range>
                <gx:altitudeMode>relativeToSeaFloor</gx:altitudeMode>
            </LookAt>
            <styleUrl>#m_ylw-pushpin</styleUrl>
            <Point>
                <gx:drawOrder>1</gx:drawOrder>
                <coordinates>-107.105195493537,40.11614841516316,0</coordinates>
            </Point>
        </Placemark>
    </Folder>
</Document>
</kml>

I run an XPath query to grab the 'Document' element....

Set xNode = .selectSingleNode("//ns:kml/ns:Document")
StrXML = xNode.xml

This is the value of StrXML...

 <Document>
    <name>data.kml</name>
    <Folder>
        <name>Temporary Places</name>
        <open>1</open>
        <Placemark>
            <name>Untitled Placemark</name>
            <LookAt>
                <gx:TimeStamp **xmlns:gx="http://www.google.com/kml/ext/2.2"**><when>2000</when>
</gx:TimeStamp>
                <longitude>-107.105195493537</longitude>
                <latitude>40.11614841516315</latitude>
                <altitude>0</altitude>
                <heading>0.0484794930795848</heading>
                <tilt>0</tilt>
                <range>209596.4338269165</range>
                <gx:altitudeMode xmlns:gx="http://www.google.com/kml/ext/2.2">relativeToSeaFloor</gx:altitudeMode>
            </LookAt>
            <styleUrl>#m_ylw-pushpin</styleUrl>
            <Point>
                <gx:drawOrder **xmlns:gx="http://www.google.com/kml/ext/2.2"**>1</gx:drawOrder>
                <coordinates>-107.105195493537,40.11614841516316,0</coordinates>
            </Point>
        </Placemark>
    </Folder>
</Document>

The XML that is returned now has the GX namespace URI, which is not present in the raw file. I simply want the XML without that namespace being inserted into the tag. Is this possible with MSXML2?

1

There are 1 answers

0
Parfait On

Consider XSLT, the special-purpose language to transform XML files. Specifically, parse out the Document tag and remove all underlying namespaces with local name (i.e., without prefix or URI). With MSXML, you can run XSLT 1.0 scripts:

XSLT (save as .xsl file which is a special .xml file)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:k="http://www.opengis.net/kml/2.2">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="*">
    <xsl:element name="{local-name(.)}">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>
  
  <xsl:template match="@*">
    <xsl:attribute name="{local-name(.)}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
  
  <xsl:template match="k:kml">
      <xsl:apply-templates select="k:Document"/>
  </xsl:template>
  
</xsl:stylesheet>

Online Demo

VBA

Public Sub RunXSLT()
    ' REFERENCE Microsoft XML, v6.0
    Dim xmlDoc As New MSXML2.DOMDocument60, xslDoc As New MSXML2.DOMDocument60, newDoc As New MSXML2.DOMDocument60
    Dim StrXML As String

    ' LOAD XML AND XSLT 
    xmlDoc.Load "C:\Path\To\Input.xml"
    xmlDoc.async = False

    xslDoc.Load "C:\Path\To\XSLTScript.xsl"
    xslDoc.async = False

    ' TRANSFORM XML TO NEW DOCUMENT
    xmlDoc.transformNodeToObject xslDoc, newDoc
    StrXML = newDoc.xml

    Set newDoc = Nothing: Set xslDoc = Nothing: Set xmlDoc = Nothing         
End Sub