your programing

내 xpath를 깨는 XML 네임 스페이스!

lovepro 2020. 10. 7. 07:59
반응형

내 xpath를 깨는 XML 네임 스페이스! [복제]


이 질문에 이미 답변이 있습니다.

다음 XML이 있습니다.

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

이것은 SharePoint 웹 서비스에서 반환되는 XML의 축소 된 버전입니다. 또한 다음 xPath가 있습니다.

/List/Fields/Field

xmlns내 XML에서 제거하면 xPath가 제대로 작동합니다. 거기에있을 때 내 xPath는 아무것도 찾지 못합니다. xPath와 다르게해야 할 일이 있습니까? XML 수정은 옵션이 아닙니다.


또한 다음 xPath가 있습니다.

/List/Fields/Field 

내 XML에서 xmlns를 제거하면 xPath가 제대로 작동합니다. 거기에있을 때 내 xPath는 아무것도 찾지 못합니다.

네임 스페이스 바인딩을 등록 할 수없고 사용할 수없는 경우 (등록 된 접두사가 "x"라고 가정) :

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

다른 방법이 있습니다 .

/*[name()='List']/*[name()='Fields']/*[name()='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 라이브러리에 해당 네임 스페이스 uri를 등록해야 할 가능성이 높습니다. 라이브러리에 따라 'default'접두사를 사용할 수 있거나 명명 된 접두사를 제공하고 xpath 쿼리에서 사용해야 할 수 있습니다.

예를 들어, DOMXPath를 사용하는 PHP (언어를 지정하지 않았기 때문에)에서 다음과 같이 할 수 있습니다.

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

Xalan-c를 사용하는 동안이 문제가 발생했습니다.

처음에 내가 얻지 못한 부분은 XPath 또는 XSLT 네임 스페이스 별칭 / 접두사가 네임 스페이스 확인자에 따라 문서의 별칭 / 접두사와 다를 수 있다는 것입니다.

문서에 네임 스페이스가 있으면 네임 스페이스를 사용하지 않는 한 경로 요소와 일치하지 않는 것으로 보입니다. (표준이지만 항상 따르지는 않습니까?)

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 

If you can skip the document element, the following XPath can also help:

//Fields/Field

This works as long as you don't have 'Fields' below any other node and as long the sub nodes have no namespace.

참고URL : https://stackoverflow.com/questions/5239685/xml-namespace-breaking-my-xpath

반응형