Perl, Libxml 및 Schemas
-
19-08-2019 - |
문제
스키마에 대해 파일을로드하고 검증하려는 예제 Perl 스크립트가 있습니다. 다양한 노드를 조사합니다.
#!/usr/bin/env perl
use strict;
use warnings;
use XML::LibXML;
my $filename = 'source.xml';
my $xml_schema = XML::LibXML::Schema->new(location=>'library.xsd');
my $parser = XML::LibXML->new ();
my $doc = $parser->parse_file ($filename);
eval {
$xml_schema->validate ($doc);
};
if ($@) {
print "File failed validation: $@" if $@;
}
eval {
print "Here\n";
foreach my $book ($doc->findnodes('/library/book')) {
my $title = $book->findnodes('./title');
print $title->to_literal(), "\n";
}
};
if ($@) {
print "Problem parsing data : $@\n";
}
불행히도 XML 파일을 잘 확인하고 있지만 $ 책 항목을 찾지 못하므로 아무것도 인쇄하지 않습니다.
XML 파일에서 스키마를 제거하고 PL 파일에서 유효성 검사를 제거하면 정상적으로 작동합니다.
기본 네임 스페이스를 사용하고 있습니다. 기본 네임 스페이스를 사용하지 않도록 변경하면 (xmlns : lib = "http://libs.domain.com"을 사용하고 lib가있는 XML 파일의 모든 항목을 접두사로 변경하고 XPATH 표현식을 변경하여 네임 스페이스 접두사를 포함하도록 XPATH 표현식을 변경하십시오 (/lib : 라이브러리/lib : book) 그런 다음 다시 파일이 작동합니다.
왜요? 그리고 내가 무엇을 놓치고 있습니까?
XML :
<?xml version="1.0" encoding="utf-8"?>
<library xmlns="http://lib.domain.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://lib.domain.com .\library.xsd">
<book>
<title>Perl Best Practices</title>
<author>Damian Conway</author>
<isbn>0596001738</isbn>
<pages>542</pages>
<image src="http://www.oreilly.com/catalog/covers/perlbp.s.gif" width="145" height="190"/>
</book>
<book>
<title>Perl Cookbook, Second Edition</title>
<author>Tom Christiansen</author>
<author>Nathan Torkington</author>
<isbn>0596003137</isbn>
<pages>964</pages>
<image src="http://www.oreilly.com/catalog/covers/perlckbk2.s.gif" width="145" height="190"/>
</book>
<book>
<title>Guitar for Dummies</title>
<author>Mark Phillips</author>
<author>John Chappell</author>
<isbn>076455106X</isbn>
<pages>392</pages>
<image src="http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg" width="100" height="125"/>
</book>
</library>
XSD :
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://lib.domain.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://lib.domain.com">
<xs:attributeGroup name="imagegroup">
<xs:attribute name="src" type="xs:string"/>
<xs:attribute name="width" type="xs:integer"/>
<xs:attribute name="height" type="xs:integer"/>
</xs:attributeGroup>
<xs:element name="library">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element maxOccurs="unbounded" name="author" type="xs:string"/>
<xs:element name="isbn" type="xs:string"/>
<xs:element name="pages" type="xs:integer"/>
<xs:element name="image">
<xs:complexType>
<xs:attributeGroup ref="imagegroup"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
해결책
로부터 xml :: libxml 문서:
XPath에 대한 일반적인 실수는 기본 네임 스페이스에서 접두사 일치 요소가없는 요소 이름으로 구성된 노드 테스트를 가정하는 것입니다. 이 가정은 잘못되었습니다 - xpath 사양에 의해, 이러한 노드 테스트는 (예 : null) 네임 스페이스에있는 요소 만 일치 할 수 있습니다. ... (그리고 나중에) ... ... 권장 방법은 사용하는 것입니다. xml :: libxml :: xpathcontext기준 치수
따라서 XPath의 관점에서 "기본"네임 스페이스가 없습니다 ... 널이 아닌 네임 스페이스의 경우 XPath에 지정해야합니다. xml :: libxml :: xpathcontext 모듈을 사용하면 xpath 표현식에서 사용할 네임 스페이스에 대한 접두사를 만들 수 있습니다.