我有以下C#代码段来使用XPath来查找正在输入的XML文件中的错误:
string xml; // the XML is passed as a parameter as the string below
using (Stream messageStream = new MemoryStream(xml))
{
IXPathNavigable source = new XPathDocument(messageStream);
XPathNavigator navigator = source.CreateNavigator();
object evaResult = navigator.Evaluate("boolean(/thinktransferDataSet/ErrorLog)"); // returns false
XPathNodeIterator iterator = navigator.Select("/thinktransferDataSet/ErrorLog/sKey"); // returns empty iterator
// Assert evaResult is true and iterator has elements. Both assertions fail
}
以下是XML文件的文本:
<?xml version="1.0" standalone="yes"?>
<thinktransferDataSet xmlns="http://tempuri.org/thinktransferDataSet1.xsd">
<ProcessHeader>
<sKey>uniqueId</sKey>
<sApplication>appname</sApplication>
<sUser>username</sUser>
<dtProcessDate>Oct 8 2015 9:58AM</dtProcessDate>
<iProcessId>5132</iProcessId>
<iTranFailureCount>2</iTranFailureCount>
<iTranSuccessCount>0</iTranSuccessCount>
</ProcessHeader>
<ErrorLog>
<sKey>uniqueId</sKey>
<sLevel>ERROR</sLevel>
<sDescription>Error in table :tablename Row:1 - Column 'comments' exceeds the MaxLength limit.</sDescription>
<sSource>69</sSource>
<dtDate>Oct 8 2015 9:59AM</dtDate>
</ErrorLog>
<ErrorLog>
<sKey>uniqueId</sKey>
<sLevel>ERROR</sLevel>
<sDescription>Test error description</sDescription>
<sSource>69</sSource>
<dtDate>Oct 8 2015 9:59AM</dtDate>
</ErrorLog>
</thinktransferDataSet>
错误由XML中一个或多个元素的存在表示。但是,使用navigator.Evaluate和navigator.Select元素下面的测试消息根本找不到元素或ErrorLog / sKey元素,即使这些XPath字符串完全在XMLSpy中工作。这可能是什么问题?
非常感谢!
答案 0 :(得分:1)
为了选择属于命名空间的元素,在任何XPath表达式中,它们的名称必须以与此命名空间关联的前缀作为前缀。您可以阅读更详细的答案here。根据您的代码,您可以更改它以使其正常工作:
IXPathNavigable source = new XPathDocument(messageStream);
var xmlNamespaceManager = new XmlNamespaceManager(navigator.NameTable);
xmlNamespaceManager.AddNamespace("x", "http://tempuri.org/thinktransferDataSet1.xsd");
object evaResult = navigator.Evaluate("boolean(/x:thinktransferDataSet/x:ErrorLog)", xmlNamespaceManager);
XPathNodeIterator iterator = navigator.Select("/x:thinktransferDataSet/x:ErrorLog/x:sKey", xmlNamespaceManager);
答案 1 :(得分:0)
你必须在你的代码中处理命名空间'xmlns =“http:... xsd”',
XPathExpression xpe = XPathExpression.Compile("boolean(/ns:thinktransferDataSet/ns:ErrorLog)");
XmlNamespaceManager xnm = new XmlNamespaceManager(navigator.NameTable);
xnm.AddNamespace("ns", "http://tempuri.org/thinktransferDataSet1.xsd");
xpe.SetContext(xnm);
object evaResult = navigator.Evaluate(xpe); // will return true as expected
答案 2 :(得分:0)
试试这个
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
List<XElement> errorLogs = doc.Descendants().Where(x => x.Name.LocalName == "ErrorLog").ToList();
XNamespace ns = errorLogs[0].Name.Namespace;
var sKeys = errorLogs.Select(x => new {
sKey = x.Element(ns + "sKey").Value
}).ToList();
}