2013-07-16 2 views
3

XML :: LibXML을 사용하고 있습니다. XPath 컨텍스트를 만들 때 사용할 수있는 네임 스페이스를 정확하게 지정할 수 있어야합니다. 그러나 컨텍스트 노드의 범위에있는 모든 네임 스페이스는 XPathContext 개체에 자동으로 등록됩니다. 나는 그 등록을 취소해야하지만 내가 컨텍스트 노드의 범위에있는 네임 스페이스의 등록을 취소 할 때 오류가 발생합니다 :컨텍스트 노드의 범위에서 네임 스페이스 등록 해제

use XML::LibXML; 
use XML::LibXML::XPathContext; 

my $xml = <<'__EOI__'; 
<?xml version="1.0"?> 
<myDoc id="myDocId"> 
    <body id="bodyId"> 
    <baz:par xmlns:baz="www.baz.com" 
      xmlns:bar="www.bar.com"> 
     <bar:id>xyz123</bar:id> 
    </baz:par> 
    </body> 
</myDoc> 
__EOI__ 

my $parser = XML::LibXML->new(); 
my $doc = $parser->parse_string($xml); 

my $xpc = XML::LibXML::XPathContext->new(); 
$xpc->registerNs('baz', 'www.baz.com'); 

my $par = ${ $xpc->findnodes('//baz:par', $doc) }[0]; 

my $xpc2 = XML::LibXML::XPathContext->new($par); 
$xpc2->unregisterNs('bar'); 

위 croaks XPathContext: cannot unregister namespace합니다. 원본을 검사하면 오류가 줄 7618 (LibXML.xs)에서 인쇄되는 것을 볼 수 있습니다. 함수 xmlXPathRegisterNs이 -1을 리턴하면 인쇄됩니다. 이 함수에 대한 유일한 설명서는 xmlsoft.org에 있습니다. 이 설명서에서는 -1 반환 값은 오류가 있음을 의미하지만 오류가 발생하는 조건을 지정하지 않음을 나타냅니다. 나는 그 삶의 방식으로 그 방법의 근원을 찾을 수 없다.

XPath specification은이 특정 작업을 허용하지 않을 수도 있지만 그 결정도 불가능합니다.

XML :: LibXML :: XPathContext를 사용하여 컨텍스트 노드의 범위에서 네임 스페이스 등록을 취소 할 수있는 방법이 있는지 또는 b) XPath에서 허용되지 않는 문서가있는 경우 누구에게 말해 줄 수 있습니까?

편집

조엘은 수동으로 네임 스페이스를 등록하지 않은 경우 네임 스페이스를 등록 취소하는 경우에만 주어진 오류가 발생 내게 보여 주었다. 그러나, 등록 취소는 여전히 잘 작동하지 않습니다 다음 bar 네임 스페이스가 아직 등록되지 않았기 때문에이

$xpc2->registerNs('bar', 'nothing'); #otherwise unregistering throws an error 
$xpc2->unregisterNs('bar'); 
my @nodes = $xpc2->find('bar:id'); 
print scalar @nodes; #I want '0', but this prints '1' 
+0

변환 후에 XML이 어떻게 나타나야하는지 보여 줄 수 있습니까? ''요소를 네임 스페이스 접두어없이''으로 쓰길 원합니까? –

+0

죄송합니다. 프로그램이하는 일에 대해 분명히해야했는데 실제로는 아무 것도 아니 었습니다. 여기에는 변화가 없습니다. 난 그냥 던져 오류없이 '바'등록을 취소하고 싶습니다. –

+0

하지만 직렬화가 없거나 나중에 다른 것이 있으면 등록 해제를 원하십니까? –

답변

1

이것은 Perl 바인딩의 제한 사항입니다. XML::LibXML 항상 registers all namespaces in scope of the context node입니다. 당신이 할 수있는 일은 질문의 편집 부분에서했던 것처럼 다른 접두사를 기존 네임 스페이스에 다시 바인딩하는 것입니다. unregisterNS으로 전화를 끊으면 원하는대로 처리해야합니다.

$xpc2->registerNs('bar', 'nothing'); # Rebind prefix 
my @nodes = $xpc2->findnodes('bar:id', $par); 
print scalar(@nodes), "\n"; # Prints 0 
+0

아,이 말이 맞습니다. "아무 것도"(네가 바라건대) 네임 스페이스 URI로 사용되지 않는다. 나는 더 명백 할 수 있고 "NULL_NS_URI"또는 그와 비슷한 것을 말할 수있다. –

0

인가? unregisterNs 호출 바로 전에 $xpc2->registerNs('bar', 'www.bar.com');을 추가하면 프로그램이 제대로 실행됩니다. 이것은 당신이 원하는 행동을 생산합니까?

업데이트에서 추가 정보 : 쿼리를 수행하는 방식에 따라 libxml 또는 XML :: LibXML의 버그가 노출 될 수 있습니다. XPathContext에 익숙하지 않아서 버그인지 아닌지 알 수 없습니다. 나는 unregisterNS을 한 후 그래서 나는 lookupNS을했다, 나를 혼란 뭔가를 시도하고 난 여전히 올바른 NS 가지고 :

$xpc2->registerNs('bar', 'www.bar.com'); 
$xpc2->unregisterNs('bar'); 
print $xpc2->lookupNs('bar') . "\n"; # print www.bar.com 

그러나, 나는 당신이 무엇을 찾고 있는지 않는 해결책이있을 수 있습니다. 대신 접두사로 'bar'를 사용하는 내가 대신 'bob'를 사용하여 시도하고 나는 당신에게 당신이 찾고있는 동작을 제공 할 수 있습니다 생각 :

$xpc2->registerNs('bob', 'www.bar.com'); 
$xpc2->unregisterNs('bob'); 
my @nodes = $xpc2->find('bob:id'); 
print scalar @nodes . "\n"; 

이 방법은 예외를 던질 수있는 find 방법을 야기하고 있어요. 이 코드는 print scalar 명령에 전달되지 않습니다.

+0

동작이 여전히 올바르지 않습니다. 고마워요.이 추가 정보를 추가하기 위해 질문을 편집했습니다. –

+0

그러나 find ('bar : id')'는 여전히 노드를 반환합니다. 나는 반환되는 것 대신에 던져 질 에러가 필요하다. –

관련 문제