选择XML节点的内部文本并添加到列表

时间:2015-06-18 14:19:53

标签: c# .net xml xml-parsing selectnodes

我有以下名为file.xml的XML文件:

<?xml version="1.0"?>
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config">
   <defaults>
      <serializer>pof</serializer>
   </defaults>
    <caching-scheme-mapping>
        <cache-mapping>
            <cache-name>broadcast-data|position</cache-name>
            <scheme-name>broadcast</scheme-name>
        </cache-mapping>
        <cache-mapping>
            <cache-name>broadcast-data|position-audit</cache-name>
            <scheme-name>broadcast-remote</scheme-name>
        </cache-mapping>
        <cache-mapping>
            <cache-name>broadcast-data|trade</cache-name>
            <scheme-name>broadcast-remote</scheme-name>
        </cache-mapping>
    </caching-scheme-mapping>
</cache-config>

我试图获取所有缓存名称的内部文本,这些名称存在于每个缓存映射节点下,并将它们全部放在列表中。我有这个Model.cs类来做这件事。

class Model
{
    private XmlDocument cacheFile = new XmlDocument();
    private List<string> cacheNames = new List<string>();
    private int nameCount = 0;


    public Model()
    {
        this.loadNames();
    }

    public void loadNames()
    {
        try //exception handling
        {
            cacheFile.Load("../../resources/file.xml");

        }
        catch (System.IO.FileNotFoundException)
        {
            Debug.WriteLine("File not found!");
            Environment.Exit(1);
        }
        catch (System.ArgumentException)
        {
            Debug.WriteLine("Invalid path!");
            Environment.Exit(1);
        }
        catch (Exception e)
        {
            Debug.WriteLine("Exception thrown!");
            Debug.WriteLine(e);
            Environment.Exit(1);
        }

        //get cache names
        XmlNodeList nodes = cacheFile.SelectNodes("/cache-config/caching-scheme-mapping/cache-mapping");

        foreach (XmlNode node in nodes)
        {
            string name = node.FirstChild.InnerText;
            cacheNames.Add(name);
            nameCount++;

        }

    }
    //accessors
    public List<string> getCacheNames()
    {
        return cacheNames;
    }
    public int getNameCount()
    {
        return nameCount;
    }

}

但是,每次我创建一个Model对象然后检查List是否已加载时,它会告诉我列表为空!似乎foreach循环从未实际运行,或者好像程序无法找到我指定的节点。请帮忙。

2 个答案:

答案 0 :(得分:2)

如果您使用LINQ to XML,这非常简单:

XNamespace ns = "http://xmlns.oracle.com/coherence/coherence-cache-config";            

var doc = XDocument.Load("../../resources/file.xml");

cacheNames = doc.Descendants(ns + "cache-name").Select(e => e.Value).ToList();

您不需要保留单独的项目数,您可以从列表中获取:

cacheNames.Count;

顺便说一下,惯用的C#使用pascal casing作为方法和属性,所以如果你坚持这个,你的方法将以大写字母开头 - 例如GetCacheNames

答案 1 :(得分:0)

这令许多人感到困惑,并且在这里多次被问过。您的XML在此处具有默认命名空间

xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"

后代元素继承祖先默认命名空间,除非另有指定(使用显式命名空间前缀或具有指向不同命名空间URI的本地默认命名空间)。使用XmlDocument,您可以使用XmlNamespaceManager向名称空间URI映射注册前缀,并在XPath查询中正确使用已注册的前缀,例如:

var nsMgr = new XmlNamespaceManager(new NameTable());
nsMgr.AddNamespace("d", "http://xmlns.oracle.com/coherence/coherence-cache-config");
var xpath = "/d:cache-config/d:caching-scheme-mapping/d:cache-mapping";
XmlNodeList nodes = cacheFile.SelectNodes(xpath, nsMgr);

无论如何,如果你刚刚开始这个,那么切换到更新的课程XDocument将是一个更好的选择。