Search code examples
sql-serverxmlxpathasp-classicxmldom

alternative to ancestor-or-self ( or select all nodes in the tree with a specific child node)


I am trying to identify all the nodes in a tree that lead to a specific node.

I am trying to accomplish this through either MSSQL XML (2005) or by the Microsoft.XMLDOM in ASP classic.

I know the logic with XPATH but SQL Server does not support the ancestor-or-self axis and XMLDOM seems to choke on the :: notation..

The xpath that works when i test it in XPATH testers is

//static[@id=6]/ancestor-or-self::static

my XML (generated recursively in sql server) looks like

<root>
  <static id="1" title="some title 1" />
  <static id="2" title="some title 2">
     <children>
        <static id="3" title="some title 3" />
        <static id="4" title="some title 4">
          <children>
            <static id="5" title="some title 5" />
            <static id="6" title="some title 6" />
          </children>
        </static>
     </children>
  </static>
  <static id="7" title="some title 7" />
</root>

the XPATH should select nodes with id (2,4,6) in any order, so i can add an attribute to all of them ..

This is for a menu system, where i only know the selected leaf, and need to mark as hilited all the nodes leading to it..

I would appreciate any assistance in either overcoming the XMLDOM choking (running xml.documentElement.selectNodes("//static[@id=6]/ancestor-or-self::static") produces the following error: Expected token 'eof' found ':'. //static[@id=6]/ancestor-or-self-->:<--:static)

or with finding an alternative solution. Maybe finding all nodes that contain the specific node (with id = 6 ) at any depth..


Solution

  • Running on W2K3, using IIS6 i tested the MSXML2.XMLDomDocument.4.0 version.

    Dim XMLDom ''# As MSXML2.DOMDocument40
    
    Set XMLDom = CreateObject("MSXML2.DOMDocument.4.0")
    Call XMLDom.setProperty("SelectionLanguage", "XPath")
    
    Call XMLDom.loadXML( {document as described above - mistakes in original xml doc)
    )
    
    
    Dim originalQuery ''# As String
    originalQuery = "//static[@id=6]/ancestor-or-self::static"
    
    Dim replacementQuery ''# As String
    replacementQuery = "//static[descendant::static[@id=6] or @id=6]"
    
    
    Dim XmlElemList ''# As MSXML2.IXMLDOMNodeList
    Set XmlElemList = XMLDom.documentElement.selectNodes(originalQuery)
    
    Dim XmlElemList2 ''# As MSXML2.IXMLDOMNodeList
    Set XmlElemList2 = XMLDom.documentElement.selectNodes(replacementQuery)
    
    Dim XmlElem ''# As MSXML2.IXMLDOMElement
    Call Response.Write("Using original query : '" & originalQuery & "' (" & XmlElemList.Length & ")<br>")
    For Each XmlElem In XmlElemList
        Call Response.Write("XmlEntry : " & XmlElem.getAttribute("id") & "<br>")
        Call Response.Write("****<br>")
    Next
    
    Call Response.Write("Using replacement query : '" & replacementQuery & "' (" & XmlElemList2.Length & ")<br>")
    For Each XmlElem In XmlElemList2
        Call Response.Write("XmlEntry : " & XmlElem.getAttribute("id") & "<br>")
        Call Response.Write("****<br>")
    Next