/ / Analizza XML usando Nokogiri ma non è in grado di risolvere gli spazi dei nomi: ruby, xml, curl, nokogiri

Analizza XML usando Nokogiri ma non è in grado di risolvere gli spazi dei nomi: ruby, xml, curl, nokogiri

Ho un messaggio XML e il mio script deve essere in grado di analizzare l'elemento nodo "AccountStatus". Il mio script funziona correttamente se l'XML è stato pubblicato senza spazi dei nomi.

Quando ho incluso gli spazi dei nomi originali, mancherà lo script quando manca una grande porzione di dati XML Nokogiri::XML(request.body.read).

Ecco l'esempio XML:

curl -i -H -X POST -d "<?xml version="1.0" encoding="utf-8" ?>
<DocuSignEnvelopeInformation xmlns="http://www.w3.org/2001/XMLSchema">
<EnvelopeStatus>
<RecipientStatuses>
<RecipientStatus>
<Type>Signer</Type>
<CustomFields />
<AccountStatus>Active</AccountStatus>
<RecipientId>ab2bf57b-72b7-48e7-8298-b1c7b56930b9</RecipientId>
</RecipientStatus>
</RecipientStatuses>
</EnvelopeStatus>
</DocuSignEnvelopeInformation>" localhost:4567/shunt?uri=http://requestb.in/1hiag0y1

Ecco il mio script:

require "rubygems"
require "sinatra"
require "uri"
require "nokogiri"
#require "pry"
#require "pp"

post "/shunt" do
puts "hello world"

xmldoc = Nokogiri::XML(request.body.read)
puts xmldoc

xmldoc.xpath("//docu:DocuSignEnvelopeInformation/EnvelopeStatus/RecipientStatuses/RecipientStatus", "docu"=>"http://www.w3.org/2001/XMLSchema").each do |node|
puts node.text
end
end

Ecco l'output:

hello world
<?xml version="1.0"?>
<DocuSignEnvelopeInformation/>

risposte:

1 per risposta № 1

problemi di arricciatura:

Sembra che il primo problema che hai è con il tuo comando di arricciatura. Nota, il comando arricciatura specifica a -H opzione, ma non specifica un'intestazione e, se provo a eseguire il comando arricciato, ottengo un errore:

curl: (6) Couldn"t resolve host "POST"

Sembra che le virgolette stiano rovinando il tuo comando. In questo comando di arricciatura:

curl -i -X POST -d "<?xml version="1.0" encoding="utf-8" ?> ...

... la prima stringa citata è:

"<?xml version="

E poi come l'arricciatura interpreta tutto dopoquello - chi lo sa. Puoi curare quel problema usando le virgolette singole attorno all'esterno del xml. Ma è molto più facile mettere l'xml in un file, quindi fare in modo che il ricciolo legga il file -d opzione con un @, come questo:

 -d @file_name

arricciatura leggerà l'xml dal file il cui nome è nome_file. Ecco un esempio:

curl -i -X POST -d @./xml_files/xml5.xml http://localhost:4567/shunt

problemi di nokogiri:

Ogni tag secondario nel tuo xml fa parte del predefinito namespace; quindi ogni nome di tag figlio è preceduto dal nome dello spazio dei nomi. Eppure, tu metti solo docu: di fronte al primo tag nel tuo xpath:

//docu:DocuSignEnvelopeInformation/EnvelopeStatus/....
^
|
missing namespace name

docu: deve precedere ogni nome del tag. Inoltre, nota che invece di specificare il docu spazio dei nomi, puoi semplicemente usare xmlns: di fronte a ogni tag nel tuo xpath. Ed è molto più semplice scrivere:

  xpath = "//xmlns:AccountStatus"

Il venditore mi ha inviato un messaggio XML

I dettagli su come ciò sarà fatto sono importanti.

Ecco un comando di arricciatura che farà a upload di file:

curl -i -F "xmlfile=@xml5.xml" http://localhost:4567/shunt

-F significa POST a upload di file. A livello locale, l'xml si trova in un file chiamato xml5.xml. Quindi, la tua app sinatra può fare questo:

post "/shunt" do
require "nokogiri"

doc = Nokogiri::XML(
params["xmlfile"][:tempfile].read
)

xpath = "//xmlns:AccountStatus"
target_tag = doc.at_xpath(xpath)
puts target_tag.text
end

Oppure, con questo comando di arricciatura:

curl -i -X POST -d @xml5.xml http://localhost:4567/shunt

... il tuo percorso sarà simile a questo:

post "/shunt" do
require "nokogiri"

doc = Nokogiri::XML(
request.body.read
)

xpath = "//xmlns:AccountStatus"
target_tag = doc.at_xpath(xpath)
puts target_tag.text
end

Intestazioni del tipo di contenuto:

Il -d opzione imposta l'intestazione Content-Type nella richiesta per:

In questo modo arricciare i dati al server utilizzando l'applicazione content-type / x-www-form-urlencoded.

Il -F opzione imposta l'intestazione Content-Type nella richiesta per:

Ciò causa l'arricciamento dei dati POST utilizzando il multipart / Form-data Content-Type