альтернатива ancestor-or-self (или выберите все узлы в дереве с определенным дочерним узлом) - PullRequest
1 голос
/ 27 февраля 2010

Я пытаюсь определить все узлы в дереве, которые ведут к конкретному узлу.

Я пытаюсь выполнить это с помощью MSSQL XML (2005) или с помощью Microsoft.XMLDOM в ASP classic.

Я знаю логику с XPATH, но SQL Server не поддерживает ось ancestor-or-self, и XMLDOM, кажется, душит запись ::.

xpath, который работает, когда я тестирую его в тестерах XPATH, равен

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

мой XML (сгенерированный рекурсивно на сервере SQL) выглядит как

<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 должен выбирать узлы с идентификатором (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 ]

4 голосов
/ 27 февраля 2010

Это ответы типа "привести в порядок".

Сначала ваша основная проблема заключается в том, что Microsoft.XMLDOM обычно загружает реализацию версии 3.0 (MSXML3.dll). MSXML3 поддерживает полный язык XPATH 1.0, но не по умолчанию. Следующее должно быть достаточным для исправления: -

dom.SetProperty "SelectionLanguage", "XPath"

Ответ Марвина включает эту строку при использовании MSXML4, но на самом деле в этом нет необходимости, поскольку XPath является языком выбора по умолчанию для 4 и выше.

Однако я использую слово должно выше, по совету. Я часто сталкивался с серверами, которые были скомпрометированы сторонним приложением, которое также включает в себя дистрибутив MSXML2, но неправильно его установил. Они заставляют Microsoft.XMLDOM и не относящуюся к версии MSXML2.DOMDocument возвращать реализацию MSXML2.dll вместо реализаций MSXML3.

Поэтому я обычно рекомендую использовать лучший ProgID - «MSXML2.DOMDocument.3.0», поскольку вы точно знаете, что получаете. Кроме того, MSXML3.dll гарантированно устанавливается на все поддерживаемые в настоящее время операционные системы Windows из коробки. Также MSXML3 оставался совместимым с ошибками в имплантации MSXML2, когда документ DOM вызывается с использованием более старого progID. Использование ProgID для конкретной версии заставляет MSXML3 более строго соответствовать стандартам XML.

1 голос
/ 27 февраля 2010

Работая на 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
...