/ / Parse XML mit Nokogiri, kann aber keine Namensräume auflösen - Ruby, XML, Curl, Nokia

Parsen Sie XML mit Nokogiri, aber Namespaces können nicht aufgelöst werden - Ruby, XML, Curl, Nokogiri

Ich habe eine XML-Nachricht und mein Skript muss das Knotenelement "AccountStatus" analysieren können. Mein Skript funktioniert korrekt, wenn das XML ohne Namespaces gepostet wird.

Wenn ich die ursprünglichen Namespaces einbezüge, wird bei der Ausführung des Skripts ein großer Teil der XML-Daten fehlen Nokogiri::XML(request.body.read).

Hier ist das XML-Beispiel:

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

Hier ist mein Skript:

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

Hier ist die Ausgabe:

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

Antworten:

1 für die Antwort № 1

Lockenprobleme:

Es sieht so aus, als ob das erste Problem, das Sie haben, mit Ihrem Curl-Befehl besteht. Beachten Sie, dass Ihr curl-Befehl a angibt -H Diese Option gibt noch keinen Header an. Wenn ich versuche, den Befehl curl auszuführen, erhalte ich eine Fehlermeldung:

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

Es sieht so aus, als würden die Anführungszeichen Ihren Befehl durcheinander bringen. In diesem Curl-Befehl:

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

... die erste zitierte Zeichenfolge lautet:

"<?xml version="

Und wie interpretiert Curl dann alles nachdas - wer weiß Sie können dieses Problem beheben, indem Sie außerhalb der XML-Datei einfache Anführungszeichen verwenden. Es ist jedoch viel einfacher, die XML-Datei in eine Datei zu packen und dann die Datei von curl lesen zu lassen -d Option mit einem @, so was:

 -d @file_name

curl liest die XML-Datei aus der Datei, deren Name Dateiname lautet. Hier ist ein Beispiel:

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

nokogiri probleme:

Jedes untergeordnete Tag in Ihrer XML-Datei ist Teil von Standard Namespace; Daher wird jedem untergeordneten Tag-Namen der Namensraumname vorangestellt. Aber Sie setzen nur docu: vor dem ersten Tag in Ihrem xpath:

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

docu: muss vorausgehen jeden Verlinke den Namen. Beachten Sie auch, dass anstelle von docu Namespace können Sie einfach verwenden xmlns: vor jedem Tag in Ihrem xpath. Und es ist viel einfacher, einfach zu schreiben:

  xpath = "//xmlns:AccountStatus"

Der Verkäufer hat mir eine XML-Nachricht geschickt

Die Details, wie das gemacht wird, sind wichtig.

Hier ist ein Curl-Befehl, der a tut Datei-Upload:

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

-F bedeutet POST a Datei-Upload. Lokal befindet sich das XML in einer Datei namens xml5.xml. Dann kann Ihre Sinatra-App dies tun:

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

Oder mit diesem Curl-Befehl:

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

... Ihre Route würde so aussehen:

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

Inhaltstyp-Header:

Das -d Diese Option setzt den Content-Type-Header in der Anforderung auf Folgendes:

Dies bewirkt, dass curl die Daten mit dem Inhaltstyp application / x-www-form-urlencoded an den Server weiterleitet.

Das -F Diese Option setzt den Content-Type-Header in der Anforderung auf Folgendes:

Dies führt dazu, dass die POST-Daten unter Verwendung der multipart / form-data Content-Type gerollt werden