破解我的xpath的Xml命名空间!

时间:2011-03-08 23:37:11

标签: xml xpath xml-namespaces

我有以下XML:

<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不是一种选择。

5 个答案:

答案 0 :(得分:98)

  

我还有以下xPath:

/List/Fields/Field 
     

当我从XML中删除xmlns时   xPath工作正常。当它在   我的xPath找不到任何东西

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

/x:List/x:Fields/x:Field

然后还有另一种方式

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

答案 1 :(得分:43)

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表达式,其方法取决于您使用的库。

答案 2 :(得分:16)

您很可能必须使用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');

答案 3 :(得分:1)

我在使用Xalan-c

时遇到了这个问题

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

似乎如果doc上有命名空间,那么除非使用命名空间,否则它无法匹配路径元素。 (标准但不总是遵循?)

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 

答案 4 :(得分:-3)

如果您可以跳过文档元素,则以下XPath也可以提供帮助:

//Fields/Field

只要您在任何其他节点下面没有“字段”并且子节点没有命名空间,这就可以正常工作。