使用C#解析XML

3
我有一个XML文件如下所示:
XML文件

我上传了这个XML文件:http://dl.dropbox.com/u/10773282/2011/result.xml。它是机器生成的XML,因此您可能需要一些XML查看器/编辑器。
我使用以下C#代码获取CoverageDSPriv/Module/*中的元素。
using System;
using System.Xml;
using System.Xml.Linq;

namespace HIR {
  class Dummy {

    static void Main(String[] argv) {

      XDocument doc = XDocument.Load("result.xml");

      var coveragePriv = doc.Descendants("CoverageDSPriv"); //.First();
      var cons = coveragePriv.Elements("Module");

      foreach (var con in cons)
      {
        var id = con.Value;
        Console.WriteLine(id);
      }
    }
  }
}

运行代码后,我得到了这个结果。
hello.exe6144008016161810hello.exehello.exehello.exe81061hello.exehello.exe!17main_main40030170170010180180011190190012200200013hello.exe!107testfunctiontestfunction(int)40131505001460600158080216120120017140140018AA

I expect to get

hello.exe
61440
...

然而,我只得到了一行很长的字符串。

  • Q1:可能出了什么问题?
  • Q2:如何获取cons中元素的数量?我尝试使用cons.Count,但它不起作用。
  • Q3:如果我需要获取<CoverageDSPriv><Module><ModuleNmae>的嵌套值,我使用以下代码:

    var coveragePriv = doc.Descendants("CoverageDSPriv"); //.First(); var cons = coveragePriv.Elements("Module").Elements("ModuleName");

我可以接受这种方式,但如果元素被深度嵌套,我可能希望有直接获取元素的方法。还有其他方法吗?

添加

var cons = coveragePriv.Elements("Module").Elements();

解决了这个问题,但对于NamespaceTable,它仍然将所有元素一起打印在一行上。

hello.exe
61440
0
8
0
1
6
1
61810hello.exehello.exehello.exe81061hello.exehello.exe!17main_main40030170170010180180011190190012200200013hello.exe!107testfunctiontestfunction(int)40131505001460600158080216120120017140140018

或者,Linq to XML可以作为更好的解决方案,如这篇帖子所述。


2
请问您能否将XML(或相关部分)以文本形式发布? - R. Martinho Fernandes
我已经做了,谢谢你指出来。 - prosseek
2个回答

4

看起来你只有一个名称为Module的元素 - 所以.Value只会返回该整个元素的InnerText。你是想要这个吗?

coveragePriv.Element("Module").Elements();

这将返回Module元素的所有子元素,这似乎是你想要的。
更新: <NamespaceTable><Module> 的子元素,但你似乎想以类似于<Module>的方式处理它,即想写出每个子元素。因此,一种笨拙的方法是为 <NamespaceTable> 添加另一个循环:
foreach (var con in cons)
{
    if (con.Name == "NamespaceTable") 
    {
        foreach (var nsElement in con.Elements()) 
        {
            var nsId = nsElement.Value;
            Console.WriteLine(nsId);
        }
    }
    else
    {
        var id = con.Value;
        Console.WriteLine(id);
    }
}

或者,也许您更愿意通过 .Descendents() 完全去正规化它们:
var cons = coveragePriv.Element("Module").Descendents();

foreach (var con in cons)
{
    var id = con.Value;
    Console.WriteLine(id);
}

它似乎可以工作,但是当元素有子节点时,它只会在一行中打印出来。 - prosseek
@prosseek,我不太明白。您能否在问题中附上您的新代码和新结果? - Kirk Woll
我详细阐述了我的问题。感谢您的帮助。 - prosseek

1
XMLElement.Value有意外的结果。在使用.net的XML时,你需要手动遍历XML树。如果元素是文本,则Value可能返回您想要的内容,但如果它是另一个元素,则不一定。
我已经做了很多XML解析,并且我发现,根据您对数据的处理方式,有更好的处理XML的方法。
1)如果计划将此数据作为文本、更多的XML或HTML输出,则可以查看XSLT转换。这是将数据转换为其他可读格式的绝佳方法。当我们想在我们的网站上显示元数据(metadata)时,我们就会使用它来将其转换成HTML。
2)研究XML序列化。C#使这个过程非常容易,因为这样你就可以在消费数据时使用常规C#对象。微软甚至有工具可以从XML创建序列化类。我通常从中开始,然后进行清理并添加自己的调整,使其按照我的愿望工作。最好的方法是将对象反序列化为XML,并查看是否与您拥有的匹配。
3)尝试Linq to XML。它将允许您像查询数据库一样查询XML。它通常会慢一些,但除非您需要绝对的性能,否则它非常适合用于最小化您的工作量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接