Xml名称空间破坏了我的xpath!

Xml名称空间破坏了我的xpath!,xml,xpath,xml-namespaces,Xml,Xpath,Xml Namespaces,我有以下XML: <List xmlns="http://schemas.microsoft.com/sharepoint/soap/"> <Fields> <Field> </Field> </Fields> </List> 当我从XML中删除xmlns时,xPath工作正常。当它在那里时,我的xPath什么也找不到。我是否应该以不同的方式使用xPath?修改XML不是一个选项。您很可能必须在xpath库

我有以下XML:

<List xmlns="http://schemas.microsoft.com/sharepoint/soap/">
 <Fields>
   <Field>
   </Field>
 </Fields>
</List>

当我从XML中删除
xmlns
时,xPath工作正常。当它在那里时,我的xPath什么也找不到。我是否应该以不同的方式使用xPath?修改XML不是一个选项。

您很可能必须在xpath库中注册该名称空间uri。根据库的不同,您可能可以使用“default”前缀,或者您可能需要为其指定一个命名前缀,并在xpath查询中使用该前缀

例如,在php中(因为您没有指定语言),使用DOMXPath可以执行以下操作:

$xpath = new DOMXPath($document);
$xpath->registerNamespace('x', 'http://schemas.microsoft.com/sharepoint/soap/');
$xpath->query('/x:List/x:Fields/x:Field');

List元素已使用默认名称空间定义,并且该名称空间中的所有元素都采用该名称空间

因此,您需要忽略元素名称空间,如下所示:

/*[local-name()='List']/*[local-name()='Fields]/*[local-name()='Field]
但这意味着xpath将使用List-Fields-Field拾取任何其他元素

您可以执行名称空间检查和本地名称检查,如下所示:

/*[local-name()='List' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']/*[local-name()='Fields' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']/*[local-name()='Field' and namespace-uri()='http://schemas.microsoft.com/sharepoint/soap/']
或者,您可以向库注册名称空间,然后显式指定该名称空间的前缀,并将其添加到xpath表达式中,xpath表达式的方法取决于您使用的库

我还有以下xPath:

/List/Fields/Field
/List/Fields/Field 
当我从XML中删除XMLN时 xPath运行良好。当它在 在那里,我的xPath什么也找不到

如果无法注册命名空间绑定且无法使用(假设注册的前缀为“x”):

那么还有另一种方法

/*[name()='List']/*[name()='Fields']/*[name()='Field']

我在使用Xalan-c时遇到了这个问题

我最初没有完全理解的一点是XPath或XSLT命名空间别名/前缀可能与文档的别名/前缀不同,这取决于您的命名空间解析器

如果文档上有名称空间,则除非使用名称空间,否则它将无法匹配path元素。(标准,但不总是遵循?)

XalanDocumentPrefixResolver将XPath或XSLT名称空间映射到URI,并尝试通过获取前缀为它们提供id—在没有前缀的情况下,它使用转换为xmlns的名称

/xmlns:List/xmlns:Fields/xmlns:Field

或者,您可以创建自己的解析器,但它仍然需要xpath中使用的最小命名空间:(

这是一个我在测试时破解的,没有内存保证

// don't care what prefix given, there can only be the one
struct NoPrefixResolver : public xalanc::PrefixResolver {

    NoPrefixResolver(const xalanc::XalanDOMString&   theURI) : m_uri(theURI){}

    virtual const xalanc::XalanDOMString*
        getNamespaceForPrefix(const xalanc::XalanDOMString&     prefix) const {
        return &m_uri;
    }

    virtual const xalanc::XalanDOMString&   getURI() const {
        return m_uri;
    }

    const xalanc::XalanDOMString    m_uri;
};

/x:List/x:Fields/x:Field 
/a:List/b:Fields/c:Field 

如果可以跳过document元素,那么以下XPath也会有所帮助:

//Fields/Field

只要在任何其他节点下没有“字段”,并且子节点没有名称空间,这种方法就行。

是的,我是.NET的人,通常我的解决方案是.NET的等效解决方案。不幸的是,我们使用的是第三方“rapid”开发环境不会给我们这样做的能力…还有,如果没有前缀,为什么它们甚至包括名称空间?(xPath的
x:
部分)有一个名称空间。它只是在这个特定的文件中使用了“default”前缀。如果该文件是
@Abe Miessler,则该文件在语义上是相同的。您在xml中提到的名称空间是根元素及其子元素的默认名称空间。在xpath中,您必须使用相同的uri名称空间,但不是相同的前缀,因为只是一个标签。如果不注册命名空间,则xpath引用uri为空的元素。您也可以使用空前缀注册命名空间,因此xpath不需要“x:”前缀。绑定命名空间的功能对于xpath库来说非常重要,如果库不提供此功能,则应将其丢弃。不是这样的不是重复的。这个问题具体说明了C#,而这严格来说是xpath/xml。而且,他的命名空间不是空的,而我的命名空间是空的。你需要一些抽象级别…你要问的是如何使用xpath表达式在默认命名空间下选择元素。这是最常见的问题。请参阅,这个答案有效,而接受的答案无效king…感谢@zode64的帮助。我一直在努力让我的xpath表达式为包含xml的名称空间工作。现在我不必再担心名称空间了。非常感谢..那么如何访问属性呢?@KaiJauk,不固定的属性总是在“无名称空间”中不管它们的父元素是否在默认名称空间的范围内。所以,没问题。当然,也可以使用
*[name()='myName']
*[name()='myPrefix:myName']
@36305啊,好的,这意味着我可以像
/*[local-name()=“mynode”和@myAttr=“value”一样使用它
?@KaiJauk Yes…如果您所指的名称空间具有前缀(xmlns:x),name()将包含前缀(x:List)。local_name()为您提供不固定的元素名称(List)。
//Fields/Field