2012-01-10 78 views
1

是否可以使用XQUERY從以下XML檢索filename屬性?我試圖用/preFileDoc/inpXML/@filename但它不工作...使用XQUERY檢索屬性值

<?xml version="1.0"?> 
<preFileDoc xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> 
    <senderId>ABC</senderId> 
    <receiverId>XYZ</receiverId> 
    <tranxCode>A001</tranxCode> 
    <inpXML version="1.0" encoding="UTF-8"> 
    <soap-env:Envelope> 
     <soap-env:Header msgcode="SPPCONVAKT" orig-system="002FTB" refid="65355ff50a172064484bf9da64c1e245" timestamp="2009-02-11 21:00:10.741" filename="SPPCONVAKT20090128001.dat"/> 
     <soap-env:Body> 
text1 
text2 
     </soap-env:Body> 
    </soap-env:Envelope> 
    </inpXML> 
</preFileDoc> 

PS:有時候filename屬性被作爲fileName在傳入XML..thinking來檢索屬性@filename@fileName值。 。它可以在單個XQUERY中實現嗎?感謝您的建議...

+0

喜marc_s:

declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/"; return /preFileDoc/inpXML//soap-env:Header/@filename 

最後,filename不同市值可以圍繞通過指定兩個工作..它是在一些開發平臺,支持查詢某些xml節點值的xquery .. – user1140422 2012-01-10 08:51:41

回答

0

您需要尊重並考慮SOAP XML命名空間!

因爲我不知道你使用的是什麼,我不能告訴你如何做到這一點 - 但還有的xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"根節點上,和你的@filename屬性是<soap-env:Header .... />節點上 - 所以你需要包括XQuery中的XML名稱空間。

在.NET/C#中,你可以做這樣的(使用「老」 XmlDocument風格,直接支持XPath):

// define test XML 
string xmlContent = 
    @"<?xml version='1.0'?> 
    <preFileDoc xmlns:soap-env='http://schemas.xmlsoap.org/soap/envelope/'> 
     <senderId>ABC</senderId> 
     <receiverId>XYZ</receiverId> 
     <tranxCode>A001</tranxCode> 
     <inpXML version='1.0' encoding='UTF-8'> 
      <soap-env:Envelope> 
       <soap-env:Header msgcode='SPPCONVAKT' orig-system='002FTB' refid='65355ff50a172064484bf9da64c1e245' timestamp='2009-02-11 21:00:10.741' filename='SPPCONVAKT20090128001.dat'/> 
       <soap-env:Body> 
       text1 
       text2 
       </soap-env:Body> 
      </soap-env:Envelope> 
     </inpXML> 
    </preFileDoc>"; 

// create XmlDocument and load test data 
XmlDocument doc = new XmlDocument(); 
doc.LoadXml(xmlContent); 

// define XML namespace manager and add the SOAP namespace to it 
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable); 
mgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"); 

// use XPath and the XML namespaces to grab the <Header> node 
// the first two nodes <preFileDoc> and <inpXML> are not inside any explicit 
// XML namespace 
// but the next two (<Envelope> and <Header>) are in the "soap" XML namespace 
XmlNode header = doc.SelectSingleNode("/preFileDoc/inpXML/soap:Envelope/soap:Header", mgr); 

// read the "filename" attribute from the header node 
if(header != null && header.Attributes["filename"] != null) 
{ 
    string fileName = header.Attributes["filename"].Value; 
} 
+0

嗨marc_s..your是如此友善,你提供了在.NET/C#中的整個解決方案......真的很感激它..我在下面的XQUERY語句中獲得了我需要的東西: - /preFileDoc/inpXML/soap-env:Envelope/soap-env:Header/@filename |/preFileDoc/inpXML/soap-env:Envelope/soap -env:Header/@ fileName – user1140422 2012-01-10 09:58:55

1

你可以把多個屬性的結合。這將是不可能的,這個屬性會出現不同的外殼多次,所以應該總是返回一個節點:

//soap-env:Header/@filename | //soap-env:Header/@fileName 

或者,你可以用小括號括它,並添加[1]背後,總是拿第一個結果。

(//soap-env:Header/@filename | //soap-env:Header/@fileName)[1] 

如果您更換一個逗號,它創建了一個序列,而不是文檔順序節點集的結合,你可以在末尾添加一個默認的爲好。也許這裏不是很有用,但也許在其他情況下:

(//soap-env:Header/@filename , //soap-env:Header/@fileName, "default.dat")[1] 

HTH!

+0

謝謝grtjn ...是的,絕對是我需要解決聯合多個屬性:) – user1140422 2012-01-10 10:29:10

1

我認爲你的XPath不完整。 /preFileDoc/inpXML/@filename中的最後一個子步驟/只匹配inpXML元素的屬性,而不匹配它的後代。解決問題

的一種方式將是//〜步驟:

/preFileDoc/inpXML//@filename 

注意,這會發現在soapenv:Body命名爲filename所有屬性了。因此

更健壯的辦法是宣佈在XQuery的soapenv前綴:

declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/"; 

return /preFileDoc/inpXML//soap-env:Header/(@filename | @fileName)