这似乎是一个奇怪的问题,但我有自己的理由!我正在尝试解析Delphi 2009项目文件(.dproj),它是项目的XML表示。我可以将文档加载到XmlDocument中,但是当我尝试访问项目中使用的单元时,SelectNodes会给我一个空列表。
该项目的一个例子如下:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
...
<ItemGroup>
<DelphiCompile Include="Package.dpk">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="vcl.dcp"/>
<DCCReference Include="Unit1.pas"/>
<DCCReference Include="Unit2.pas"/>
<DCCReference Include="Unit3.pas"/>
<DCCReference Include="Unit4.pas"/>
<DCCReference Include="Unit5.pas"/>
...
</ItemGroup>
</Project>
代码示例如下:
ProjectDocument.Load(FileName);
XmlNodeList nodeList;
XmlElement RootNode = ProjectDocument.DocumentElement;
string xmlns = RootNode.Attributes["xmlns"].Value;
// This gives an empty list
nodeList = RootNode.SelectNodes("/Project/ItemGroup/DCCReference");
foreach (XmlNode title in nodeList)
{
Console.WriteLine(title.InnerXml);
}
// This also gives an empty list
nodeList = RootNode.SelectNodes("/ItemGroup/DCCReference");
foreach (XmlNode title in nodeList)
{
Console.WriteLine(title.InnerXml);
}
问题是,我做错了什么,因为我必须遗漏一些东西。唯一奇怪的是文档不是.xml,它是.dproj。
所以,如果你能解决这个问题,请提前谢谢。
标记
答案 0 :(得分:3)
<强>说明强>
如果XPath表达式需要命名空间解析,则必须使用 SelectNodes 重载,该重载以XmlNamespaceManager为参数。 XmlNamespaceManager 用于解析名称空间。
注意如果XPath表达式不包含前缀,则假定名称空间URI是空名称空间。如果您的XML包含默认命名空间,您仍然必须使用 XmlNamespaceManager 并为其添加前缀和命名空间URI;否则,您将无法选择任何节点。
您需要two-argument version of SelectNodes
。另请注意,您选择的节点没有内容,因此InnerXML
属性将为空。一旦获得非空列表,您的代码仍将打印一个空行列表。
答案 1 :(得分:2)
您需要使用XmlNamespaceManager:
var nsmgr = new XmlNamespaceManager(ProjectDocument.NameTable);
nsmgr.AddNamespace("x", ProjectDocument.DocumentElement.NamespaceURI);
var nodes = doc.SelectNodes("descendant::x:DCCReference", nsmgr);
答案 2 :(得分:0)
另外,为什么不使用自己的简单解析器解析DPR文件?找到用途 line,然后抓住每一行,删除注释和最后一个逗号,直到你用分号打一行。
好处#2除了更简单的解析之外,这适用于每个delphi版本,而DPROJ和等效文件与delphi版本到版本的着名不同。