2012-01-10 69 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)