祖先或自我的替代(或选择具有特定子节点的树中的所有节点)

时间:2010-02-26 22:06:10

标签: sql-server xml xpath asp-classic xmldom

我正在尝试识别树中通往特定节点的所有节点。

我试图通过MSSQL XML(2005)或ASP classic中的Microsoft.XMLDOM来实现这一目标。

我知道XPATH的逻辑,但SQL Server不支持ancestor-or-self轴,而XMLDOM似乎会阻塞::表示法。

我在XPATH测试人员中测试它时的xpath是

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

我的XML(在sql server中递归生成)看起来像

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

XPATH应该以任何顺序选择id(2,4,6)的节点,所以我可以为所有节点添加一个属性..

这是一个菜单系统,我只知道所选择的叶子,并且需要将所有节点标记为hilited ...

如果克服XMLDOM窒息,我将不胜感激 (正在运行xml.documentElement.selectNodes("//static[@id=6]/ancestor-or-self::static")会产生以下错误:Expected token 'eof' found ':'. //static[@id=6]/ancestor-or-self-->:<--:static

或寻找替代解决方案。也许在任何深度找到包含特定节点(id = 6)的所有节点。

2 个答案:

答案 0 :(得分:4)

这是一种“整理松散的目的”的答案。

首先,您的主要问题是“Microsoft.XMLDOM”通常会加载3.0版实现(MSXML3.dll)。 MSXML3支持完整的XPATH 1.0语言,但默认情况下不支持。以下应该足以修复: -

dom.SetProperty "SelectionLanguage", "XPath"

Marvin的回答在使用MSXML4时包含了这一行,但由于XPath是4及以上版本的默认选择语言,因此并不是必需的。

但我建议在上面使用应该这个词。我经常遇到被第三方应用程序攻陷的服务器,第三方应用程序也包含MSXML2的分发但是安装不正确。它们导致“Microsoft.XMLDOM”和非特定于版本的“MSXML2.DOMDocument”返回MSXML2.dll实现而不是MSXML3实现。

因此我通常建议使用最好的ProgID是“MSXML2.DOMDocument.3.0”,因为你确切知道你得到了什么。此外,MSXML3.dll保证安装在所有当前支持的Windows操作系统上。当使用较旧的progID调用DOM Document时,MSXML3仍然与MSXML2实现中的错误兼容。使用特定于版本的ProgID会使MSXML3更严格地符合XML标准。

答案 1 :(得分:1)

在W2K3上运行,使用IIS6我测试了MSXML2.XMLDomDocument.4.0版本。

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