5

So I'm sure this is solvable, but it's just I don't normally have to deal with XML namespaces in VBA XML code. So, we have a file which is in fact an SVG file called Flag_of_the_United_Kingdom.svg and here is the file contents

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" width="1200" height="600">
  <clipPath id="t">
    <path d="M30,15 h30 v15 z v15 h-30 z h-30 v-15 z v-15 h30 z"/>
  </clipPath>
  <path d="M0,0 v30 h60 v-30 z" fill="#00247d"/>
  <path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
  <path d="M0,0 L60,30 M60,0 L0,30" clip-path="url(#t)" stroke="#cf142b" stroke-width="4"/>
  <path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
  <path d="M30,0 v30 M0,15 h60" stroke="#cf142b" stroke-width="6"/>
</svg>

This is just an example SVG file, but it holds for other SVG files, for Internet Explorer to render the file it needs the namespace attribute on the root element.

However, I want to open an SVG file in VBA and start manipulating it and my code is tripping on the namespace issue. Here is my code which is housed in a standard module in a workbook in same directory ...

Option Explicit

Sub LoadSVGFile()
    '* Tools->References->Microsoft Xml, v6.0

    Dim fso As Object
    Set fso = VBA.CreateObject("Scripting.FileSystemObject")

    Dim sSVGPath As String
    sSVGPath = fso.BuildPath(ThisWorkbook.Path, "Flag_of_the_United_Kingdom.svg")
    If fso.FileExists(sSVGPath) Then

        Dim dom As MSXML2.DOMDocument60
        Set dom = New MSXML2.DOMDocument60

        dom.Load sSVGPath

        Debug.Assert dom.parseError = 0

        'xmlns="http://www.w3.org/2000/svg
        'dom.namespaces.Add "http://www.w3.org/2000/svg", "xmlns"

        dom.setProperty "SelectionNamespaces", "xmlns=""http://www.w3.org/2000/svg"""
        'Call dom.setProperty("SelectionLanguage", "XPath")

        Dim xmlSVG As MSXML2.IXMLDOMElement
        Set xmlSVG = dom.SelectSingleNode("svg")
        Debug.Assert Not dom.SelectSingleNode("svg") Is Nothing
        Debug.Assert Not dom.SelectSingleNode("/svg") Is Nothing

        If xmlSVG Is Nothing Then End

        '* rest of code follows here but is not shown
        Debug.Print "'* rest of code follows here but is not shown"
    End If

End Sub

The above code works when I have removed the namespace attribute from the root element, but that is no good because these files get generated by Inkscape etc.

I'm sure it is a SelectionNamespaces property issue, but I cannot get it to work, I'm sure someone could solve this easily.

UPDATE: Googling around on this looks like this is the expected behaviour re https://support.microsoft.com/en-gb/kb/288147

S Meaden
  • 8,050
  • 3
  • 34
  • 65

1 Answers1

5

as far as i remember, selectionNamespace is a list of namspaces/prefixes for use in the selection language (xPath). It is used to switch between namespaces in xPath. Try it like this:

 dom.setProperty "SelectionNamespaces", "xmlns:svg=""http://www.w3.org/2000/svg"""

    Dim xmlSVG As MSXML2.IXMLDOMElement
    Set xmlSVG = dom.SelectSingleNode("svg:svg")
    Debug.Assert Not dom.SelectSingleNode("svg:svg") Is Nothing
    Debug.Assert Not dom.SelectSingleNode("/svg:svg") Is Nothing

P.S.: It's been a while since i last used Windows, so i can not garantee anything :-(

Holger Will
  • 7,228
  • 1
  • 31
  • 39
  • 1
    Sadly, given the link I edited into question this looks correct but I'm not happy about introducing a fake namespace. – S Meaden Jan 18 '17 at 14:34
  • 1
    it's not a fake namespace, ist just a prefix which you use to tell xPath wich namespace you are talking about. the namespace is the `http://www.w3.org/2000/svg`-part. I think what you want is to tell xPath that the svg namespace should be treated as the default namespace. I don't think that's possible... – Holger Will Jan 18 '17 at 14:38