Xpathを使用してdc:title
要素を取得しようとしています。次のコードを使用してメタデータを取得できます。
doc = <<END
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0">
<metadata xmlns:dc="URI">
<dc:title>title text</dc:title>
</metadata>
</package>
END
doc = Nokogiri::XML(doc)
# Awesome this works!
puts '//xmlns:metadata'
puts doc.xpath('//xmlns:metadata')
# => <metadata xmlns:dc="URI"><dc:title>title text</dc:title></metadata>
ご覧のとおり、上記は正しく動作しているようです。ただし、このノードツリーからタイトル情報を取得できないようです。以下のすべてが失敗します。
puts doc.xpath('//xmlns:metadata/title')
# => nil
puts doc.xpath('//xmlns:metadata/dc:title')
# => ERROR: `evaluate': Undefined namespace prefix
puts doc.xpath('//xmlns:dc:title')
# => ERROR: 'evaluate': Invalid expression: //xmlns:dc:title
上記のxml docを使用して、xpathで名前空間を使用する方法を誰かに説明してもらえますか?.
すべての名前空間は、解析時に登録する必要があります。のこぎりは、ルートノードに名前空間を自動的に登録します。ルートノード上にない名前空間は、自分で登録する必要があります。これはうまくいくはずです:
puts doc.xpath('//dc:title', 'dc' => "URI")
または、名前空間を完全に削除することもできます。これは、競合するノード名がないことが確実な場合にのみ行ってください。
doc.remove_namespaces!
puts doc.xpath('//title')
'http://www.idpf.org/2007/opf'
名前空間URIに適切に登録された接頭辞opf
、および'URI'
にdc
を使用すると、次のものが必要です。
/*/opf:metadata/dc:title
注:xmlns
およびxml
は、組み込みの'http://www.w3.org/2000/xmlns/'
および'http://www.w3.org/XML/1998/namespace'
以外の名前空間URIにバインドできない予約済みのプレフィックスです。
名前空間URIのハッシュを明示的に作成する代わりに、名前空間定義が定義されているxml要素から名前空間定義を取得できます。
あなたの例を使用して:
# First grab the metadata node, because that's where "dc" is defined.
metadata = doc.at_xpath('//xmlns:metadata')
# Pass metadata's namespaces as the resolver.
metadata.at_xpath('dc:title', metadata.namespaces)
2番目のxpathも可能性があることに注意してください。
doc.at_xpath('//dc:title', metadata.namespaces).to_s
しかし、祖先が近い場合、なぜルートから検索するのでしょうか。また、名前空間を定義する要素とその子を名前空間の「スコープ」と見なす必要があります。限定されたスコープを検索することで混乱が少なくなり、微妙なバグを回避できます。