Perl、LibXML、およびスキーマ
-
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ファイルは正常に検証されますが、$ bookアイテムが見つからないため、何も印刷されません。
XMLファイルからスキーマを削除し、PLファイルから検証を削除すると、正常に機能します。
デフォルトのネームスペースを使用しています。デフォルトのネームスペース(xmlns:lib = <!> quot; http://libs.domain.com <!> quot;を使用しないように変更し、XMLファイル内のすべてのアイテムにlibをプレフィックスし、XPath式を名前空間プレフィックス(/ lib:library / 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>
解決
XPathに関するよくある間違いは、 ノードテストが プレフィックスが一致しない要素名 デフォルト名前空間の要素。 この仮定は間違っています-XPathによる 仕様、そのようなノードテストは noにある要素のみに一致します (つまり、null)名前空間。 ...(そして 後で)... ...推奨される方法は XML :: LibXML :: XPathContext を使用します モジュール
したがって、XPathの観点からは、<!> quot; default <!> quot;はありません。名前空間... null以外の名前空間の場合、XPathで指定する必要があります。 XML :: LibXML :: XPathContextモジュールを使用すると、XPath式で使用する名前空間のプレフィックスを作成できます。