views:

304

answers:

2

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

+1  A: 

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
Marvin Smit
Yes, that seems to be the problem.. changing it to either version 4 or 5 did the trick... Thank you very much :) *i was using the `Microsoft.XMLDOM` which loaded the version 2 :o*
Gaby
+2  A: 

This a "tidy up the loose ends" sort of answers.

First your primary problem would be that "Microsoft.XMLDOM" would normally load version 3.0 implementation (MSXML3.dll). MSXML3 does support the full XPATH 1.0 language but not by default. The follow should be enough to fix:-

dom.SetProperty "SelectionLanguage", "XPath"

Marvin's answer includes this line when using MSXML4 but it isn't really necessary since XPath is the default selection language on 4 and above.

However I use the word should above advisedly. I've often come across servers that have been compromised by a third-party application which also include a distribution of MSXML2 but install it incorrectly. They cause "Microsoft.XMLDOM" and the non version specific "MSXML2.DOMDocument" to return an MSXML2.dll implementation instead of MSXML3 implementations.

I therefore normally recommend that the best ProgID to use is "MSXML2.DOMDocument.3.0" since you know exactly what you are getting. In addition MSXML3.dll is guaranteed to be installed on all currently supported Windows OSes out of the box. Also MSXML3 remained compatible with bugs in the MSXML2 implentation when the DOM Document is invoked using an older progID. Using the version specific ProgID causes MSXML3 to conform more strictly to XML standards.

AnthonyWJones
+1, Excellent info there Anthony, thanks for following up.. (*should that be comprised and not compromised ?*)
Gaby
Defaults are evil! They seem to change over time. Guess there's no question which selection language its using when reaching XML 10.0 ;)
Marvin Smit
@Marvin: Defaults are great they certainly not evil, without defaults our code would be much harder to write. For example, are your XPaths in your every day code peppered with `child::` in order to avoid relying on the fact the `child::` is the __default__ axis used by XPath? I put out these "tidy up" answers to ensure there are no mis-conceptions about what is really going on. It could be construde from your code that specifying XPath is necessary, it isn't. However I would agree there is certain comfort that comes from being explicit about it anyway.
AnthonyWJones
@Gaby: No I did mean compromised. I've seen working ASP applications fail when a system administrator installed some other piece of third-party software that should have not had any affect on the ASP application. It was __compromised__ by a bad install of MSXML2.
AnthonyWJones
@Anthony, gotcha
Gaby