ruby/rails strip out xml code based on regex expression - ruby-on-rails

I receive the following xml in a database field.
<Request type="Final">
<Field name="Grade">94.5</Field>
<Field name="EmployeeName">2398;;;Mike5</Field>
<Field name="Date">051215</Field>
</Request>
Currently, I just receive it and display them as it is:
def request_xml
(request.blank? ? "" : request.message)
end
Now, I want to return the xml by stripping of the EmployeeName value to nil i.e 2398;;;Mike5 from 2398;;;Mike5 based on certain logic
So I am ok with 2 solutions
> 1. if EmployeeName value matches a regex, return null else return the value as it is?
> - Return <Field name="EmployeeName"></Field>
> 2. if EmployeeName value matches a regex completely strip out the whole EmployeeName XML: <Field
> name="EmployeeName">2398;;;Mike5</Field> from the result
Is either of the above solution possible via ruby/rails code?

As #asiniy already answered, you can use nokogiri for changing your xml, like this:
UPDATE: you can filter tag contents with the following code:
require 'nokogiri'
xml = Nokogiri::XML('<Request type="Final">
<Field name="Grade">94.5</Field>
<Field name="EmployeeName">2398;;;Mike5</Field>
<Field name="Date">051215</Field>
</Request>')
# remove all Employee elements, containing text 2398
xml.css('Field[name=EmployeeName]').select { |node| node.text =~ /2398/ }.map(&:remove)
puts xml
will output
<?xml version="1.0"?>
<Request type="Final">
<Field name="Grade">94.5</Field>
<Field name="Date">051215</Field>
</Request>

You can do it through nokogiri gem. Here is official tutorial
require 'nokogiri'
xml = Nokogiri::XML('<Request type="Final">
<Field name="Grade">94.5</Field>
<Field name="EmployeeName">2398;;;Mike5</Field>
<Field name="Date">051215</Field>
</Request>')
if xml.xpath('//EmployeeName')
do_whatever_you_want

Related

How to set a default field value in some form view in Odoo?

How to set default value in Job_id in this form with xml and don't need to set in the python file?
<record id="form_student_stu" model="ir.ui.view">
<field name="name">Student Info</field>
<field name="model">youth_and_scholarship.youth_and_scholarship</field>
<field name="arch" type="xml">
<form string="Job Form" version="9.0">
<div class="widget_box">
<div class="widget_title"><h5>Student Information</h5></div>
<div>
<group col="1">
<field name="image" widget="image" class="oe_avatar oe_left" nolabel="1"/>
<field name="Job_id" invisible="1"/>
</group>
<group>
<field name="Kname" placeholder="First Name and Last Name..." string="Name in Khmer" style="width:40%%"/>
<field name="Ename" placeholder="First Name and last Name..." string="Name in Latin" style="width:40%%"/>
<field name="Gender" string="Gender" style="width:40%%"/>
<field name="DOB" string="Date of birth"/>
<field name="Job_work" string="Accupation" style="width:40%%"/>
</group>
</div>
</div>
</form>
</field>
</record>
You can use some context specifying an XML ID (External ID). You can add the default value to the action which calls the view like this:
<record id="youth_and_scholarship_youth_and_scholarship_action" model="ir.actions.act_window">
<field name="name">Student Info</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">youth_and_scholarship.youth_and_scholarship</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="context">{'default_job_id': ref('xml_id')}</field>
</record>
If you open the view from a field, from a many2one for example, you can add the context to that field:
<field name="field_name" context="{'default_job_id': ref('xml_id')}" />
If haven't set the XML ID of the record you can get the ID by Python code and return an action window with the context:
job_id = self.get_job_id()
return {
'name': 'Student Info',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'youth_and_scholarship.youth_and_scholarship',
'context': {'default_job_id': job_id }
}
NOTES:
The key always has to be: default_ + field_name: database_id
You can see all the XML IDs here: Settings > Technical > Sequences & Identifiers > External Identifiers > Complete ID

How to get value of particular name in xml file

<ecomexpress-objects version="1.0">
<object pk="1" model="awb">
<field type="BigIntegerField" name="awb_number">700054480</field>
<field type="CharField" name="orderid">5012</field>
<field type="FloatField" name="actual_weight">0.5</field>
<field type="CharField" name="origin">DELHI-DSW</field>
<field type="CharField" name="destination">DELHI-DLN</field>
<field type="CharField" name="customer">Ecom Express Private Limited - 32012</field>
<field type="CharField" name="consignee">MUKESH KUMAR GUPTA</field>
<field type="CharField" name="pickupdate">11-Feb-2013</field>
<field type="CharField" name="status">Delivered / Closed</field>
<field type="CharField" name="reason_code"/>
<field type="CharField" name="reason_code_description"/>
<field type="CharField" name="reason_code_number">999</field>
<field type="CharField" name="receiver">mukesh 9999488339</field>
<field type="CharField" name="expected_date">12-Feb-2013</field>
<field type="CharField" name="last_update_date">05-Apr-2013</field>
<field type="CharField" name="delivery_date">2013-02-17 11:26:00</field>
<field type="CharField" name="ref_awb">None</field>
<field type="CharField" name="rts_shipment"/>
<field type="CharField" name="system_delivery_update">2013-02-17 11:26:00 </field>
<field type="CharField" name="rts_system_delivery_status"/>
<field name="scans">
<object pk="1" model="scan_stages">
<field type="DateTimeField" name="updated_on">05 Apr, 2013, 19:40 hrs</field>
<field type="CharField" name="status">SAL Tally closed</field>
<field type="CharField" name="reason_code"/>
<field type="CharField" name="reason_code_number"/>
<field type="CharField" name="location">DLN</field>
<field type="CharField" name="Employee">Umesh Jaswanti - 10015</field>
</object>
<object pk="2" model="scan_stages">
<field type="DateTimeField" name="updated_on">05 Apr, 2013, 19:39 hrs</field>
<field type="CharField" name="status">SAL Tally closed</field>
<field type="CharField" name="reason_code"/>
<field type="CharField" name="reason_code_number"/>
<field type="CharField" name="location">DLN</field>
<field type="CharField" name="Employee">Umesh Jaswanti - 10015</field>
</object>
</field>
</object>
</ecomexpress-objects>
i know the simple file xml file like
<HEUREKA>
<CATEGORY>
<CATEGORY_ID>971</CATEGORY_ID>
<CATEGORY_NAME>Auto-moto</CATEGORY_NAME>
</CATEGORY>
<CATEGORY>
<CATEGORY_ID>881</CATEGORY_ID>
<CATEGORY_NAME>Alkohol testery</CATEGORY_NAME>
<CATEGORY_FULLNAME>Heureka.cz | Auto-moto | Alkohol testery</CATEGORY_FULLNAME>
</CATEGORY>
</HEUREKA>
how to read itand get particular value but in first case i want to get status = 'Delivered / Closed'
how can i get it..
of it is there any tutorial to read the file any get the value then please share with me
I think you should try Nokogiri gem.

Nokogiri : NoMethodError (undefined method `inner_html' for nil:NilClass)

I'm trying to parse a simple XML data with nokogiri.
this is my XML:
POST /.... HTTP/1.1
Host: ....
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://...."
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="...." xmlns:xsd="...." xmlns:soap="....">
<soap:Body>
<WS_QueryOnSec xmlns="......">
<type>string</type>
<ID>string</ID>
</WS_QueryOnSec>
</soap:Body>
</soap:Envelope>
and this is my simle request:
require "nokogiri"
#doc = Nokogiri::XML(request.body.read)
#something = #doc.at('type').inner_html
But Nokogiri can not find the Type or ID node.
When I change the data into this every thing works fine:
<soap:Body>
<type>string</type>
<ID>string</ID>
</soap:Body>
It seems the problem is the raw text above the data and the nods with xmlns or the other attributes!
What do you recommend to resolve this ?
The first "XML" isn't XML. It's text that contains XML. Remove the header information down to the blank line and try it again.
I think it'd help you to read the XML spec or to read some tutorials about creating XML which will help you understand how it's defined. XML is a tight specification and doesn't allow any deviation. The syntax is pretty flexible, but you have to play by its rules.
Consider these examples:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
foo
<root>
<node />
</root>
EOT
doc.errors # => [#<Nokogiri::XML::SyntaxError: Start tag expected, '<' not found>]
Removing the text, which is outside the root tag results in a proper parse:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<root>
<node />
</root>
EOT
doc.errors # => []
<root> isn't neccesarily the name of the "root" node, it's just the outermost tag:
doc = Nokogiri::XML(<<EOT)
<foo>
<node />
</foo>
EOT
doc.errors # => []
and still results in a valid DOM/internal representation of the document:
puts doc.to_html
# >> <foo>
# >> <node></node>
# >> </foo>
Your XML sample is using namespaces, which complicate matters somewhat. The Nokogiri documentation talks about how to deal with them, so you'll want to understand that part of parsing XML because you'll encounter it again. Here's the easy way of working with them:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:xsi="...." xmlns:xsd="...." xmlns:soap="....">
<Body>
<WS_QueryOnSec xmlns="......">
<type>string</type>
<ID>string</ID>
</WS_QueryOnSec>
</Body>
</Envelope>
EOT
namespaces = doc.collect_namespaces
doc.at('type', namespaces).text # => "string"

How to convert XML to Hash in ruby?

I have a XML code which I want to convert into Hash
<meta_description><language id="1"></language><language id="2"></language></meta_description>
<meta_keywords><language id="1"></language><language id="2"></language></meta_keywords>
<meta_title><language id="1"></language><language id="2" ></language></meta_title>
<link_rewrite><language id="1" >konsult-500-krtim</language><language id="2" >konsult-500-krtim</language></link_rewrite>
<name><language id="1" >Konsult 500 kr/tim</language><language id="2" >Konsult 500 kr/tim</language></name>
<description><language id="1" ></language><language id="2" ></language></description>
<description_short><language id="1" ></language><language id="2" ></language></description_short>
<available_now><language id="1" ></language><language id="2" ></language></available_now>
<available_later><language id="1" ></language><language id="2" ></language></available_later>
<associations>
<categories nodeType="category" api="categories">
<category>
<id>2</id>
</category>
</categories>
<images nodeType="image" api="images"/>
<combinations nodeType="combination" api="combinations"/>
<product_option_values nodeType="product_option_value" api="product_option_values"/>
<product_features nodeType="product_feature" api="product_features"/>
<tags nodeType="tag" api="tags"/>
<stock_availables nodeType="stock_available" api="stock_availables">
<stock_available>
<id>111</id>
<id_product_attribute>0</id_product_attribute>
</stock_available>
</stock_availables>
<accessories nodeType="product" api="products"/>
<product_bundle nodeType="product" api="products"/>
</associations>
I want to convert this xml into Hash .
I try to find functions which convert this xml to h=Hash.new
How I do this?
There is ActiveSupport's Hash#from_xml method that you can use:
xml = File.open("data.xml").read # if your xml is in the 'data.xml' file
Hash.from_xml(xml)
If you are using Rails you can use the answer provided above, otherwise you can require the ActiveSuppport gem:
require 'active_support/core_ext/hash'
xml = '<foo>bar</foo>'
hash = Hash.from_xml(xml)
=>{"foo"=>"bar"}
Note this will only work with valid xml. See comments on op. Also note that using element attributes like id="1" won't convert back the same way for example:
xml = %q(
<root>
<foo id="1"></foo>
<bar id="2"></bar>
</root>).strip
hash = Hash.from(xml)
=>{"root"=>{"foo"=>{"id"=>"1"}, "bar"=>{"id"=>"2"}}}
puts hash.to_xml
# will output
<?xml version="1.0" encoding="UTF-8"?>
<hash>
<root>
<foo>
<id>1</id>
</foo>
<bar>
<id>2</id>
</bar>
</root>
</hash>
Use nokogiri to parse XML response to ruby hash. It's pretty fast.
require 'active_support/core_ext/hash' #from_xml
require 'nokogiri'
doc = Nokogiri::XML(response_body)
Hash.from_xml(doc.to_s)

error 400 bad request with XEP-0055?

I got possible fields from my server:
<iq xmlns="jabber:client" from="vjud.company.com" to="testuser#company.com/iPhone" id="search1" type="result"><query xmlns="jabber:iq:search">
<instructions>You need an x:data capable client to search</instructions>
<x xmlns="jabber:x:data" type="form">
<title>Search users in vjud.company.com</title>
<instructions>Fill in the form to search for any matching Jabber User (Add * to the end of field to match substring)
</instructions>
<field type="text-single" label="User" var="user"/>
<field type="text-single" label="Full Name" var="fn"/>
<field type="text-single" label="Name" var="first"/>
<field type="text-single" label="Middle Name" var="middle"/>
<field type="text-single" label="Family Name" var="last"/>
<field type="text-single" label="Nickname" var="nick"/>
<field type="text-single" label="Birthday" var="bday"/>
<field type="text-single" label="Country" var="ctry"/>
<field type="text-single" label="City" var="locality"/>
<field type="text-single" label="Email" var="email"/>
<field type="text-single" label="Organization Name" var="orgname"/>
<field type="text-single" label="Organization Unit" var="orgunit"/>
</x>
</query>
</iq>
Suppose I want to search a user with JID admin#company.com
Composed request wil look like this:
XMPPIQ *iq2 = [[XMPPIQ alloc] init];
[iq2 addAttributeWithName:#"type" stringValue:#"set"];
[iq2 addAttributeWithName:#"from" stringValue:#"testuser#company.com"];
[iq2 addAttributeWithName:#"to" stringValue:#"vjud.company.com"];
[iq2 addAttributeWithName:#"id" stringValue:#"search1"];
XMPPElement *query2 = [XMPPElement elementWithName:#"query"];
[query2 setXmlns:#"jabber:iq:search"];
XMPPElement *user = [XMPPElement elementWithName:#"user"];
[user setStringValue:#"admin"];
[iq2 addChild:query2];
[query addChild:user];
The error stanza:
<iq xmlns="jabber:client" from="vjud.company.com" to="testuser#company.com/iPhone" type="error" id="search1">
<query xmlns="jabber:iq:search"/>
<error code="400" type="modify">
<bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
</iq>
So, basically there are 2 questions:
Why there is no </query> element in response?
Is it the actual reason of the error?
-The server's response should look like this-
Big thanks to #legoscia user, in case request was composed right, you will get something like this(notice <item> element):
<iq xmlns="jabber:client" from="vjud.company.com" to="testuser#company.com/iPhone" id="search1" type="result»>
<query xmlns="jabber:iq:search"><x xmlns="jabber:x:data" type="result»>
<title>Search Results for vjud.company.com</title>
<reported>
<field type="text-single" label="Jabber ID" var="jid»/>
<field type="text-single" label="Full Name" var="fn»/>
<field type="text-single" label="Name" var="first»/>
<field type="text-single" label="Middle Name" var="middle»/>
<field type="text-single" label="Family Name" var="last"/><field type="text-single" label="Nickname" var="nick»/>
<field type="text-single" label="Birthday" var="bday»/>
<field type="text-single" label="Country" var="ctry»/>
<field type="text-single" label="City" var="locality»/>
<field type="text-single" label="Email" var="email»/>
<field type="text-single" label="Organization Name" var="orgname"/><field type="text-single" label="Organization Unit" var="orgunit»/>
</reported>
<item>
<field var="jid»>
<value>admin#company.com</value>
</field>
<field var="fn"><value/></field>
<field var="last"><value/></field>
<field var="first"><value/></field>
<field var="middle"><value/></field>
<field var="nick"><value/></field>
<field var="bday"><value/></field>
<field var="ctry"><value/></field>
<field var="locality"><value/></field>
<field var="email"><value/></field>
<field var="orgname"><value/></field>
<field var="orgunit"><value/></field></item>
</x>
</query>
</iq>
If there is no matches,you will just receive <reported> element with lots of fields. You may want to have look at this as well.
This search service doesn't support "plain" XEP-0055 search fields, but requires you to submit the x:data form returned in the response to the "get" request; see XEP-0004.
You can tell this by the fact that the result doesn't contain any suggested search fields as children of the query element (see example 2 of XEP-0055), and also the <instructions/> element says so. This means that you need to look at the <x xmlns="jabber:x:data" type="form"> element and submit it.
Thus, you need to send something like:
<iq type='set'
from='juliet#capulet.com/balcony'
to='characters.shakespeare.lit'
id='search4'
xml:lang='en'>
<query xmlns='jabber:iq:search'>
<x xmlns='jabber:x:data' type='submit'>
<field var='user'>
<value>admin</value>
</field>
</x>
</query>
</iq>
(This is example 8 from XEP-0055, modified to search for the user with username "admin".)

Resources