2009-10-05 71 views
4

我已經加載了一個XML文檔,現在我希望運行一個XPath查詢來選擇XML的某個子集。 XML是Delphi/MSXML:XPath查詢失敗

<?xml version="1.0"?> 
<catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> 
    <book id="bk101"> 
     <author>Gambardella, Matthew</author> 
     <title>XML Developer's Guide</title> 
     <genre>Computer</genre> 
     <price>44.95</price> 
     <publish_date>2000-10-01</publish_date> 
     <description>An in-depth look at creating applications with 
     XML.</description> 
    </book> 
</catalog> 

,並且程序進行類似

procedure RunXPathQuery(XML: IXMLDOMDocument2; Query: string); 
begin 

    XML.setProperty('SelectionLanguage', 'XPath'); 

    NodeListResult := XML.documentElement.selectNodes(Query)); 

    ShowMessage('Found (' + IntToStr(NodeListResult.length) + ') nodes.'); 

end; 

問題是:當我運行XPath查詢對上述XML「/目錄」,返回(如預期)的節點列表1個元素。但是,如果我從 <catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>中刪除:xsi並重新運行該查詢,則返回的節點列表爲空。如果我刪除整個'xmlns'屬性,那麼生成的節點列表再次具有1個元素。所以我的問題是這樣的:我可以做些什麼來彌補這一點,即如何讓MSXML返回正確數量的實例(在運行XPath查詢時),而不管命名空間(或其他屬性)如何?

謝謝!

+0

要麼我讀這個(http://support.microsoft.com/kb/288147)完全錯誤的,或對於特定版本的MSXML,不可能使用XPath的默認命名空間。不幸的是,我使用MSXML v6.0,所以這不應該影響我。任何人有類似的經歷? – conciliator 2009-10-05 13:09:01

回答

3

請參閱this link

當您使用<catalog xmlns='http://www.w3.org/2001/XMLSchema-instance'>時,整個節點將移動到不同的(默認)名稱空間。您的XPath不在這個其他名稱空間內查找,因此無法找到任何數據。用<catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>你只是聲明xsi作爲一個不同的命名空間。這將是與默認名稱空間不同的名稱空間。

我現在不能測試,但添加一些like this可能幫助:

XML.setProperty('SelectionNamespaces', 'xmlns=''http://www.w3.org/2001/XMLSchema-instance'''); 

或者,也許它沒有。正如我所說,我現在無法測試它。

+0

感謝工作坊亞歷克斯!這很有道理。不幸的是,它似乎並沒有做到這一點(但是),但我會多玩一點。 – conciliator 2009-10-05 11:48:35

1

用途:

document.setProperty('SelectionNamespaces', 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"') 
+0

...然後查詢'/ xsi:catalog'而不是'/ catalog'。 – 2009-10-05 17:31:45

2

想通了。看來我的問題已被描述爲herehere(並且很可能還有其他數十億個其他地方)。

查詢/ * [local-name()='catalog']適用於我。

0
/*[local-name()='catalog'] 

是一個解決您的問題。 但是你爲什麼要忽略命名空間?他們已被介紹來表達某些東西,例如區分不同類型的目錄。通過您的查詢,您現在可以選擇世界上任何目錄的內容,但我認爲您只能處理書籍。如果您獲得螺釘或汽車目錄,會發生什麼?

前面提到的有關前綴(xsi)的內容是正確的。如果刪除前綴,則所有元素都位於該名稱空間中(然後稱爲默認名稱空間)。但你仍然可以處理它。

在你的代碼中,無論如何都要給命名空間一個前綴。它甚至不需要匹配原始前綴:

XML.setProperty('SelectionNamespaces', "xmlns:xyz='http://www.w3.org/2001/XMLSchema-instance'"); 

第二件事是適應XPath查詢。它必須是

/xyz:catalog 

原始XML只聲明xsi命名空間,但從未使用它。在這種情況下,您可以完全刪除它。如果你要使用的命名空間,你想要的前綴,然後重寫你的XML

<?xml version="1.0"?> 
<xsi:catalog xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> 
    <xsi:book id="bk101"> 
    <xsi:author>Gambardella, Matthew</xsi:author> 
    <xsi:title>XML Developer's Guide</xsi:title> 
    <xsi:genre>Computer</xsi:genre> 
    <xsi:price>44.95</xsi:price> 
    <xsi:publish_date>2000-10-01</xsi:publish_date> 
    <xsi:description>An in-depth look at creating applications with 
    XML.</xsi:description> 
</xsi:book> 
</xsi:catalog>