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

Selecting inner text of XML nodes and adding to list

我有以下名为 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 可以做到这一点。

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;
    }

}

但是,每次我创建一个模型对象然后检查列表是否被加载时,它告诉我列表是空的!看起来好像 foreach 循环从未真正运行过,或者好像程序找不到我指定的节点。请帮忙。

如果你使用LINQ来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.

这让很多人感到困惑,并且在 SO 中被问过很多次。您的 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);

无论如何,如果您刚刚开始这个,切换到更新的 class XDocument 将是一个更好的选择。