XPath和XML:多个命名空间

6

所以我有一个看起来像这样的文档

<a xmlns="uri1" xmlns:pre2="uri2">
 <b xmlns:pre3="uri3">
   <pre3:c>
     <stuff></stuff>
     <goes></goes>
     <here></here>
   </pre3:c>
   <pre3:d xmlns="uri4">
     <under></under>
     <the></the>
     <tree></tree>
   </pre3:d>
  </b>
</a>

我希望得到一个可以获取<under>的xpath表达式。

这个元素的namespaceURI是uri4。

目前我的表达式看起来像:

//ns:a/ns:b/pre3:d/pre4:under

我让名称空间管理器为默认名称空间(在这种情况下为uri1)添加了“ns”,并使用pre2、pre3和pre4分别定义了它们的uri2、uri3和uri4。
我收到错误消息“表达式必须计算为节点集”。
我知道该节点存在。 我知道直到我的xpath中的pre4:under之前的所有内容都正常工作,因为我在文档的其余部分中使用它而没有任何问题。 是额外的pre4:under导致了错误,我不确定原因。
有什么想法吗?
谢谢。
解决方法:
感谢大家坚持认为这是正确的-确实如此。 但是...在我的代码中,我将“pre4”作为“64”(一个变量),它不喜欢将整数用作前缀。 将其更改为“d”+ myintvariable即可。

使用您描述的确切方式注册命名空间后,该表达式应选择您想要的“under”元素。我认为您需要提供更多上下文信息。 - user357812
抱歉如果这是一个愚蠢的问题,但我找不到任何关于pre4命名空间的定义。这只是因为打错了吗,还是可能存在问题? - Jon Egerton
我想不出还能给什么了。Jon,在调用表达式之前,我使用nsmgr.AddNamespace("pre4", navigator.NamespaceURI)。(是的,这是正确的方法。)也许问题在于我不应该定义第二个默认命名空间? - emragins
好问题,加1。请看我的答案,其中包含一个完整且简短的C#应用程序,该程序成功使用了您问题中的XPath表达式并生成了正确的结果。 - Dimitre Novatchev
2个回答

3

我猜测您使用的XML导航实现中可能存在缺陷。使用SketchPath,以下XPath成功地导航到了节点:

/def:a/def:b/pre3:d/def2:under

你可以尝试为XPath中的命名空间指定不同的前缀。否则,如果性能不是真正的问题,并且它是唯一的节点,你可以尝试使用//under


很遗憾,不能保证它是唯一节点。我将尝试在完整文档和相关表达式中使用sketchpath工具,并查看情况如何。 - emragins

0

你的代码中有一个错误,但你没有向我们展示它

这个C#控制台应用程序:

using System;
using System.Xml;


namespace Namespaces
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(
                @"<a xmlns='uri1' xmlns:pre2='uri2'>
                    <b xmlns:pre3='uri3'>
                        <pre3:c>
                            <stuff></stuff>
                            <goes></goes>
                            <here></here>
                        </pre3:c>
                        <pre3:d xmlns='uri4'>
                            <under></under>
                            <the></the>
                            <tree></tree>
                        </pre3:d>
                    </b>
                </a>"                
                       );
            XmlNamespaceManager nsman = 
                new XmlNamespaceManager(new NameTable());
            nsman.AddNamespace("ns", "uri1");
            nsman.AddNamespace("pre2", "uri2");
            nsman.AddNamespace("pre3", "uri3");
            nsman.AddNamespace("pre4", "uri4");

            Console.WriteLine(
                doc.SelectSingleNode("/")
                  .SelectNodes("//ns:a/ns:b/pre3:d/pre4:under",

                                nsman)[0].OuterXml
                              );
        }
    }
}

当执行时,会产生所需的正确结果:

<under xmlns="uri4"></under>

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