programing

xpath를 깨는 xml 네임스페이스!

javamemo 2023. 10. 7. 09:06
반응형

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에서 xPath를 제거하면 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 - Fields를 가진 다른 요소를 선택함을 의미합니다.

네임스페이스 검사는 물론 로컬 이름 검사도 다음과 같이 수행할 수 있습니다.

/*[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 식에 추가할 수도 있습니다.

해당 네임스페이스 uri를 xpath 라이브러리에 등록해야 할 가능성이 높습니다.라이브러리에 따라 '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');

잘란씨를 사용하는 동안 이 문제가 발생했습니다.

처음에는 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 

문서 요소를 건너뛸 수 있는 경우 다음 XPath도 도움이 됩니다.

//Fields/Field

이것은 다른 노드 아래에 '필드'가 없고 하위 노드에 네임스페이스가 없는 경우에 작동합니다.

언급URL : https://stackoverflow.com/questions/5239685/xml-namespace-breaking-my-xpath

반응형