1

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

我正在尝试通过 MSSQL XML (2005) 或 ASP 经典中的 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)的所有节点..

4

2 回答 2

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 文档时,MSXML3 仍然与 MSXML2 实现中的错误兼容。使用特定于版本的 ProgID 会使 MSXML3 更严格地符合 XML 标准。

于 2010-02-27T19:46:08.120 回答
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
于 2010-02-27T00:30:32.560 回答