C# 从xml文件获取节点

C# 从xml文件获取节点,c#,xml,winforms,C#,Xml,Winforms,如何解析xml文件 <?xml version="1.0" encoding="UTF-8"?> <sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <sitemap> <loc>link</loc> <lastmod>2011-08-17T08:23:17+00:00</lastmod> </sitem

如何解析xml文件

<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
<sitemap> 
    <loc>link</loc>
    <lastmod>2011-08-17T08:23:17+00:00</lastmod> 
</sitemap> 
<sitemap>
    <loc>link</loc> 
    <lastmod>2011-08-18T08:23:17+00:00</lastmod> 
</sitemap> 
</sitemapindex>

站点地图有两个子节点“loc”和“lastmod”。您正在访问的节点是“name”和“url”。这就是为什么你没有得到任何结果。此外,在XML文件中,最后一个站点地图标记未正确关闭,请尝试xn[“loc”].InnerText,然后查看是否得到所需的结果

问题在于
sitemapindex
元素定义了一个默认名称空间。选择节点时需要指定名称空间,否则将找不到它们。例如:

XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("s", "http://www.sitemaps.org/schemas/sitemap/0.9");
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager);
XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("s", xml.DocumentElement.NamespaceURI); //Using xml's properties instead of hard-coded URI
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager);
通常来说,在使用
XmlNameSpaceManager
时,可以将前缀保留为空字符串,以指定希望该名称空间成为默认名称空间。所以你会认为你可以做这样的事情:

// WON'T WORK
XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("", "http://www.sitemaps.org/schemas/sitemap/0.9"); //Empty prefix
XmlNodeList xnList = xml.SelectNodes("/sitemapindex/sitemap", manager); //No prefixes in XPath
但是,如果您尝试该代码,您会发现它找不到任何匹配的节点。原因是在XPath 1.0(XmlDocument实现的)中,当没有提供名称空间时,它总是使用空名称空间,而不是默认名称空间。因此,在
XmlNamespaceManager
中指定默认名称空间并不重要,反正XPath不会使用它。引用以下文件中的相关段落:

节点测试中的QName使用扩展名扩展为扩展名 表达式上下文中的命名空间声明。这是一样的 开始标记和结束标记中元素类型名称的扩展方式 除了不使用用xmlns声明的默认名称空间外:if QName没有前缀,则名称空间URI为null(此 与展开属性名称的方式相同)。如果 QName有一个前缀,该前缀在 表达式上下文

因此,当您正在读取的元素属于名称空间时,您无法避免在XPath语句中添加名称空间前缀。但是,如果您不想麻烦将名称空间URI放入代码中,您可以使用
XmlDocument
对象返回根元素的URI,在本例中,这就是您想要的。例如:

XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("s", "http://www.sitemaps.org/schemas/sitemap/0.9");
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager);
XmlDocument xml = new XmlDocument();
xml.Load("sitemap.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xml.NameTable);
manager.AddNamespace("s", xml.DocumentElement.NamespaceURI); //Using xml's properties instead of hard-coded URI
XmlNodeList xnList = xml.SelectNodes("/s:sitemapindex/s:sitemap", manager);

我肯定会使用LINQtoXML,而不是旧的基于XmlDocument的XMLAPI。您可以使用下面的代码完成您想要做的事情。注意,我将试图获取其值的元素的名称更改为'loc'和'lastmod',因为这是示例XML中的内容('name'和'url'不存在):

XElement元素=XElement.Parse(XMLFILE);
IEnumerable list=element.Elements(“站点地图”);
foreach(列表中的元素e)
{
字符串LOC=e.元素(“LOC”).值;
字符串LASTMOD=e.Element(“LASTMOD”).Value;
}

它不工作怎么办?它是否成功加载文件?if是否找到这两个站点地图元素?它是否读取站点地图的子元素?我假设元素标记之前的破折号不在实际的xml文件中,对吗?xnList没有填充。(对于破折号表示抱歉-没有破折号)正如OP在评论中所说,问题不在于读取名称和url,问题在于
xnList
是空的。明白了吗。我的第二点是XML文件有一个未关闭的标记“sitemap”。因此,当列表由站点地图标记填充时,由于最后一个站点地图标记而出现错误。很抱歉,XML文件是正确的,我修复了上面的示例。上面SteveDog的例子很好用。你的例子很好用!非常感谢。有没有办法在不指定名称的情况下访问默认名称空间?@Andrew很乐意帮忙!我在回答中添加了一些关于名称空间的附加信息。