2009-05-08 9 views
5

Mam następujący dokument XML:Jak ustawić Nokogiri tak, aby rozumiał moje przestrzenie nazw?

<samlp:LogoutRequest ID="123456789" Version="2.0" IssueInstant="200904051217"> 
    <saml:NameID>@[email protected]</saml:NameID> 
    <samlp:SessionIndex>abcdefg</samlp:SessionIndex> 
</samlp:LogoutRequest> 

chciałbym uzyskać zawartość SessionIndex (czyli „abcdefg”) z niego. Próbowałem to:

XPATH_QUERY = "LogoutRequest[@ID][@Version='2.0'][IssueInstant]/SessionIndex" 
SAML_XMLNS = 'urn:oasis:names:tc:SAML:2.0:assertion' 
SAMLP_XMLNS = 'urn:oasis:names:tc:SAML:2.0:protocol' 

require 'nokogiri' 
doc = Nokogiri::XML(xml) 
doc.xpath(XPATH_QUERY, 'saml' => SAML_XMLNS, 'samlp' => SAMLP_XMLNS) 

ale otrzymuję następujące błędy:

Nokogiri::XML::SyntaxError: Namespace prefix samlp on LogoutRequest is not defined 
Nokogiri::XML::SyntaxError: Namespace prefix saml on NameID is not defined 
Nokogiri::XML::SyntaxError: Namespace prefix samlp on SessionIndex is not defined 

Próbowałem dodawanie nazw do kwerendy XPath, ale to niczego nie zmienia.

Dlaczego nie mogę przekonać Nokogiri, że przestrzenie nazw są ważne?

Odpowiedz

6

Wygląda na to, że przestrzenie nazw w tym dokumencie nie są poprawnie zadeklarowane - powinny być atrybuty xmlns:samlp i xmlns:saml w węźle głównym. W takich przypadkach, Nokogiri zasadniczo ignoruje nazw (ponieważ nie można odwzorować je do urny lub URI), więc XPath działa jeśli je usunąć, tj

doc.xpath(XPATH_QUERY) 
+0

który wydaje mi dać te same błędy ... w niektórych sytuacjach. Robiąc to dosłownie w Ib działa dobrze, ale działa moje specs nadal wieje. Garr. –

+0

Gotowy! Nokogiri zwraca węzeł "błędu", który owija węzeł, który znalazł, ale jest to _really_did_find_the_node_! –

9

Widzę dwie opcje dla Ciebie:

  1. Usuń wszystkie przestrzenie nazw

    http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Document#remove_namespaces%21-instance_method

    brute force sposób to zrobić. Może prowadzić do problemów w przypadku kolizji przestrzeni nazw.

  2. Zastosowanie collect_namespaces

    http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Document#collect_namespaces-instance_method

    dużo lepszym rozwiązaniem. Możesz użyć tego jeden raz, aby zidentyfikować przestrzenie nazw (powiedzmy w irb) i zakodować je.

    LUB

    Użyj go w czasie wykonywania, i dostarczyć go jako drugi argument do http://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#xpath-instance_method

+0

'collect_namespaces' to dobrze wiedzieć – mikezter

Powiązane problemy