Xml命名空间打破我的xpath!

问题描述:

我有以下XML:Xml命名空间打破我的xpath!

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

这正从一个SharePoint Web服务返回的XML的一个简化版本。我也有以下XPath:

/List/Fields/Field 

当我从XML删除xmlns中的XPath工作正常。当它在我的xPath中找不到任何东西。有什么我应该做的与我的xPath不同?修改XML不是一种选择。

+2

许多重复之一:http://*.com/questions/11345/xpaths-and-default-namespaces – 2011-03-09 19:45:28

+2

没有,这不是重复。这个问题特别指出了C#,而这是严格的xpath/xml。而且,他的命名空间不是空白的,而我的是。 – 2011-03-21 14:37:51

+0

您需要某种程度的抽象......您在问如何使用XPath表达式在默认名称空间下选择元素。 **这是最常见的**。 – 2011-03-21 16:09:36

我也有以下XPath:

/List/Fields/Field 

当我从XML 删除的xmlns中的XPath工作正常。当它在 有我的XPath觉得没有什么

如果不能注册,命名空间绑定,不能使用(假设注册前缀为“X”):

/x:List/x:Fields/x:Fiels 

则有另一种方式

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

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

例如,在PHP(因为你没有指定语言)使用DOMXPath你可以做这样的事情:

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

是啊,我是一个.NET人,通常我的解决方案就是.NET的等价物。不幸的是,我们正在使用第三方的“快速”开发环境,它不会使我们有能力做到这一点...... – 2011-03-09 00:03:00

+1

另外,如果没有前缀,他们为什么还要包含一个名称空间? (xPath的'x:'部分) – 2011-03-09 00:03:44

+1

有一个名称空间。它只是在这个特定的文件中使用'默认'前缀。该文件将是相同的语义是吧'' – Anomie 2011-03-09 00:10:13

列表元素已经定义了默认的命名空间,这是由采用里面的所有元素。

你因此需要忽略,像这样的元素命名空间:

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

但这意味着与XPath将拿起任何其他元素与列表 - 田 - 现场

你可以做一个命名空间检查以及像这样的本地名称检查:

/*[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表达式,其方法依赖于您正在使用的库。

+1

这个答案正在工作,而接受的答案不工作....谢谢@ zode64这个帮助。我疯狂地让我的xpath表达式为包含xml的名称空间工作。现在,我不需要担心名称空间了。万分感谢.. – 2016-02-09 13:43:45

我刚刚一直有这个问题,而使用的Xalan-C

我最初不太明白的一点是,XPath或XSLT命名空间别名/前缀可能与文档不同 - 取决于您的命名空间解析器。

看起来,如果文档上有一个命名空间,那么它将无法匹配路径元素,除非使用了命名空间。 (标准但并不总是遵循?)

的XalanDocumentPrefixResolver将XPath或XSLT命名空间映射到URI和尝试,并通过获取前缀给它们编号 - 这里没有前缀它使用它变成的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 

如果你可以跳过文档元素,下面的XPath还可以帮助:

//Fields/Field 

这个工作,只要你没有“字段”下的任何其他节点和大的子节点有没有名字空间。