是否可以使用XQUERY从以下XML中检索属性filename
?我正在尝试使用 /preFileDoc/inpXML/@filename
,但它不起作用......
<?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
属性在传入的XML中发送为fileName
。思考从属性@filename
或@fileName
中检索值..它可以实现单XQUERY?谢谢你的建议...
答案 0 :(得分:2)
我认为您的XPath不完整。 /
中的最后一个子步骤/preFileDoc/inpXML/@filename
仅匹配inpXML
元素的属性,而不匹配其后代。
解决问题的一种方法是//
- 步骤:
/preFileDoc/inpXML//@filename
请注意,这也会在filename
中找到名为soapenv:Body
的所有属性。
因此,更健壮的方法是在XQuery中声明soapenv
前缀:
declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/";
return /preFileDoc/inpXML//soap-env:Header/@filename
最后,filename
的不同大写可以通过指定两者来解决:
declare namespace soap-env="http://schemas.xmlsoap.org/soap/envelope/";
return /preFileDoc/inpXML//soap-env:Header/(@filename | @fileName)
答案 1 :(得分: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!
答案 2 :(得分:0)
您需要尊重并考虑SOAP XML名称空间!
由于我不知道您在使用什么,我无法告诉您如何执行此操作 - 但根节点上有xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
,@filename
属性位于<soap-env:Header .... />
1}} node - 所以你需要在XQuery中包含XML命名空间。
在.NET / C#中,您可以这样做(使用直接支持XPath的“旧版”XmlDocument
样式):
// 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;
}