¿Cómo puedo extraer los nombres de nodo para el documento XML fragmentado usando Ruby?
parsing tags (1)
Usando Nokogiri, puede tratar la cadena como un Fragmento de Documento, luego encontrar los nodos incrustados:
require ''nokogiri''
doc = Nokogiri::XML::DocumentFragment.parse(<<EOT)
Hello, there <RECALL>first_name</RECALL>. Thanks for giving me your email.
<SETPROFILE><NAME>email</NAME><VALUE><star/></VALUE></SETPROFILE>. I have just sent you something.
EOT
nodes = doc.search(''*'').each_with_object({}){ |n, h|
h[n] = n.text
}
nodes # => {#<Nokogiri::XML::Element:0x3ff96083b744 name="RECALL" children=[#<Nokogiri::XML::Text:0x3ff96083a09c "first_name">]>=>"first_name", #<Nokogiri::XML::Element:0x3ff96083b5c8 name="SETPROFILE" children=[#<Nokogiri::XML::Element:0x3ff96083a678 name="NAME" children=[#<Nokogiri::XML::Text:0x3ff960836884 "email">]>, #<Nokogiri::XML::Element:0x3ff96083a650 name="VALUE" children=[#<Nokogiri::XML::Element:0x3ff96083a5c4 name="star">]>]>=>"email", #<Nokogiri::XML::Element:0x3ff96083a678 name="NAME" children=[#<Nokogiri::XML::Text:0x3ff960836884 "email">]>=>"email", #<Nokogiri::XML::Element:0x3ff96083a650 name="VALUE" children=[#<Nokogiri::XML::Element:0x3ff96083a5c4 name="star">]>=>"", #<Nokogiri::XML::Element:0x3ff96083a5c4 name="star">=>""}
O, más legiblemente:
nodes = doc.search(''*'').each_with_object({}){ |n, h|
h[n.name] = n.text
}
nodes # => {"RECALL"=>"first_name", "SETPROFILE"=>"email", "NAME"=>"email", "VALUE"=>"", "star"=>""}
Obtener el contenido de una etiqueta en particular es fácil, entonces:
nodes[''RECALL''] # => "first_name"
Iterar sobre todas las etiquetas también es fácil:
nodes.keys.each do |k|
...
end
Incluso puede reemplazar una etiqueta y su contenido por texto:
doc.at(''RECALL'').replace(''Fred'')
doc.to_xml # => "Hello, there Fred. Thanks for giving me your email. /n<SETPROFILE>/n <NAME>email</NAME>/n <VALUE>/n <star/>/n </VALUE>/n</SETPROFILE>. I have just sent you something./n"
Cómo reemplazar las etiquetas anidadas se le deja como ejercicio.
I un documento similar a XML que es preprocesado por un sistema fuera de mi control. El formato del documento es así:
<template>
Hello, there <RECALL>first_name</RECALL>. Thanks for giving me your email.
<SETPROFILE><NAME>email</NAME><VALUE><star/></VALUE></SETPROFILE>. I have just sent you something.
</template>
Sin embargo, solo recibo como cadena de texto lo que está entre las etiquetas <template>
.
Me gustaría poder extraer sin especificar las etiquetas con anticipación al analizar. Puedo hacer esto con la gema Crack pero solo si las etiquetas están al final de la cadena y solo hay una.
Con Crack, puedo poner una cuerda como
string = "<SETPROFILE><NAME>email</NAME><VALUE>[email protected]</VALUE></SETPROFILE>"
y mi salida de Crack es:
{"SETPROFILE"=>{"NAME"=>"email", "VALUE"=>"[email protected]"}}
Entonces puedo usar una declaración de case
para los posibles valores que me importan.
Dado que necesito tener varias <tags>
en la cadena y no pueden estar al final de la cadena, ¿cómo puedo analizar fácilmente los nombres de nodo y los valores, de forma similar a lo que hago con crack?
Estas etiquetas también deben ser eliminadas. Me gustaría continuar usando la excelente sugerencia de @TinMan.
Funciona perfectamente una vez que conozco el nombre de la etiqueta. La cantidad de etiquetas será finita. Envío la etiqueta al método apropiado una vez que lo sé, pero primero tiene que analizarse fácilmente.