3

好的,所以我整天都在为 XPATH 和 C# 中的这个问题而烦恼。

我有以下 XML 文档:

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0"     xmlns:c="http://base.google.com/cns/1.0">
  <item id="362">
    <title>Family Holiday</title>
    <description>a long, wordy description goes here</description>
    <g:id xmlns:g="g">FPS</g:id>
    <g:latitude xmlns:g="g">42.502260</g:latitude>
    <g:longitude xmlns:g="g">1.532850</g:longitude>
  </item>
 </entry>

然后我执行以下操作:

XmlDocument _xmlDocument = new XmlDocument();
_xmlDocument.Load(xmlfile);

XmlNamespaceManager _nameSpaceManager = new XmlNamespaceManager(_xmlDocument.NameTable);
_nameSpaceManager.AddNamespace("RN", "http://www.w3.org/2005/Atom");
_nameSpaceManager.AddNamespace("g", "http://base.google.com/ns/1.0");
_nameSpaceManager.AddNamespace("c", "http://base.google.com/cns/1.0");

XPathNavigator navigator = _xmlDocument.CreateNavigator();

我的问题在于:

XmlNode nde = _xmlDocument.SelectSingleNode("/RN:entry/RN:item/g:id", _nameSpaceManager);

返回 null - 不是 Id 节点。然而,

XmlNode nde = _xmlDocument.SelectSingleNode("/RN:entry/RN:item/RN:title", _nameSpaceManager);

确实返回标题节点。

任何关于我做错了什么的想法都将不胜感激!

干杯西蒙

4

3 回答 3

3

我希望"/RN:entry/RN:item/g:id"XPath 表达式返回 null - 在您的 XPath 中,g:命名空间别名是指命名空间“http://base.google.com/ns/1.0”,但是在您的 XML 文档中,g:命名空间别名已被修改为引用idlatitudelongitude元素上的命名空间“g” 。

删除xmlns:g="g"每个元素上的命名空间别名定义,它应该按预期工作 - 命名空间别名定义是从父 XML 元素继承的,因此不需要这些别名(以及不正确)

<entry xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
  <item id="362">
    <title>Family Holiday</title>
    <description>a long, wordy description goes here</description>
    <g:id>FPS</g:id>
    <g:latitude>42.502260</g:latitude>
    <g:longitude>1.532850</g:longitude>
  </item>
</entry>

如果您想修改代码以使用未修改的 XML,则改为更改g:代码中命名空间声明的定义以匹配 XML 中的定义

_nameSpaceManager.AddNamespace("g", "g");
于 2012-10-15T16:19:01.407 回答
3

您的本地命名空间声明覆盖了根命名空间定义;

<g:id xmlns:g="g">FPS</g:id>

实际上是说这里的 g:id 属性来自命名空间 'g' 与 g 定义为来自文档元素中的命名空间不同。

例如,如果我将您的 XML 更改为:

  string xml = @"<entry xmlns=""http://www.w3.org/2005/Atom"" xmlns:g=""http://base.google.com/ns/1.0""     xmlns:c=""http://base.google.com/cns/1.0"">
                  <item id=""362"">
                    <title>Family Holiday</title>
                    <description>a long, wordy description goes here</description>
                    <g:id xmlns:g=""http://base.google.com/ns/1.0"">FPS</g:id>
                    <g:latitude xmlns:g=""http://base.google.com/ns/1.0"">42.502260</g:latitude>
                    <g:longitude xmlns:g=""http://base.google.com/ns/1.0"">1.532850</g:longitude>
                  </item>
                 </entry>";

或者简单地说:

string xml = @"<entry xmlns=""http://www.w3.org/2005/Atom"" xmlns:g=""http://base.google.com/ns/1.0""     xmlns:c=""http://base.google.com/cns/1.0"">
                      <item id=""362"">
                        <title>Family Holiday</title>
                        <description>a long, wordy description goes here</description>
                        <g:id>FPS</g:id>
                        <g:latitude>42.502260</g:latitude>
                        <g:longitude>1.532850</g:longitude>
                      </item>
                     </entry>";

您的 XPath 表达式现在作为本地命名空间g与文档元素命名空间声明匹配g

如果你被 XML 卡住了,那么你唯一能做的就是:

XmlNamespaceManager _nameSpaceManager = new XmlNamespaceManager(_xmlDocument.NameTable);
_nameSpaceManager.AddNamespace("RN", "http://www.w3.org/2005/Atom");
_nameSpaceManager.AddNamespace("g", "g");
_nameSpaceManager.AddNamespace("c", "http://base.google.com/cns/1.0");

您的 XPath 现在可以工作了。

使用 XmlDocument、.Net Framework 版本 4 进行测试。

于 2012-10-15T16:20:52.853 回答
0

只需更换您的线路:

_nameSpaceManager.AddNamespace("g", "http://base.google.com/ns/1.0");

_nameSpaceManager.AddNamespace("g", "g");
于 2012-10-15T16:44:27.487 回答