How to parse SOAP XML in ruby? - ruby

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="https://extranet.mcs.be/DEV_QUALITY_API/modules/quality/services/soap/quality.php"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getQuestionnairesListResponse>
<return SOAP-ENC:arrayType="ns1:QuestionnaireListItem[34]"
xsi:type="ns1:ArrayOfQuestionnaireListItem">
<item xsi:type="ns1:QuestionnaireListItem">
<ID xsi:type="xsd:string">0000000022</ID>
<Code xsi:type="xsd:string">Interest PubTransp</Code>
<Reference xsi:type="xsd:string">Check Employees Interest in Public
Transport</Reference>
</item>
<item xsi:type="ns1:QuestionnaireListItem">
<ID xsi:type="xsd:string">0000000008</ID>
<Code xsi:type="xsd:string">CS SRE North 2003</Code>
<Reference xsi:type="xsd:string">Customer Satisfaction SRE North 2003</Reference>
</item>
<item xsi:type="ns1:QuestionnaireListItem">
<ID xsi:type="xsd:string">0000000006</ID>
<Code xsi:type="xsd:string">CS SRE South 2003</Code>
<Reference xsi:type="xsd:string">Customer Satisfaction SRE South 2003</Reference>
</item>
.
.
.
I want to parse the above soap String (I actually want to get items from the above soap). How could I do this?

There's a gem called Savon that's specifically made for dealing with SOAP in Ruby.
There's good documentation on the web site, once you looked into that and have more specific questions I'm sure we can help you.

Related

magento 2.0 and 2.1 massaction compatibility issue admin back-end

We have a custom written Magento 2 module that adds an action to the order overview dropdown.
Now have we ran into an issue where it would work on 2.0.x but not 2.1.x and up.
After a bit of research it is caused by Magento changing an xml node from container to listingToolbar.
Now my question is, how do we make our module compatible with both 2.0.x and 2.1.x?
Adding both; container and listingToolbar will break the massaction dropdown.
magento 2.0.x version:
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<container name="listing_top">
<massaction name="listing_massaction">
<action name="new_action">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">action_name</item>
<item name="label" xsi:type="string" translate="true">Action Name Text Here</item>
<item name="url" xsi:type="url" path="vendor_module/action"/>
</item>
</argument>
</action>
</massaction>
</container>
magento 2.1.x version:
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="new_action">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">action_name</item>
<item name="label" xsi:type="string" translate="true">Action Name Text Here</item>
<item name="url" xsi:type="url" path="vendor_module/action"/>
</item>
</argument>
</action>
</massaction>
</listingToolbar>

Multiple referring pratictioners in an FHIR Encounter

I want to express the following use case :
A patient is pregnant. She's seen by two specialists : an endocrinologist and an obstetric gynecologist.
The gynecologist sends her to the hospital, for a care he can't give.
The patient has then :
a family doctor
a referring doctor (obstetric gynecologist)
a specialist (endocrinologist)
The family doctor is referenced in the Patient Resource, by the generalPractitioner element.
But I want to reference the two others practitioners in the Encounter Resource.
I'm ok with the first (the referring), but I don't know where to reference the second.
<?xml version="1.0" encoding="UTF-8"?>
<Encounter xmlns="http://hl7.org/fhir">
<id value="99289910"/>
<contained>
<ReferralRequest>
<id value="p1"/>
<status value="active"/>
<category value="request"/>
<requester>
<reference value="Practitioner/99003499686"/>
<identifier>
<type>
<coding>
<system value="http://hl7.org/fhir/v2/0443"/>
<code value="RP"/>
<display value="Referring Provider"/>
</coding>
<text value="Referring doctor"/>
</type>
<system value='urn:oid:1.2.250.1.71.4.2.1'></system>
<value value='99003499686'/>
<assigner><display value="RPPS"/></assigner>
</identifier>
</requester>
</ReferralRequest>
</contained>
<status value="finished"/>
<class>
<system value="http://hl7.org/fhir/v3/ActCode"/>
<code value="IMP"/>
</class>
<patient>
<reference value="/patient/3803218"/>
</patient>
<incomingReferral>
<reference value="#p1"/>
</incomingReferral>
<period>
<start value="2016-09-07T15:39:00"/>
<end value="2016-09-11T16:35:00"/>
</period>
<location>
<location>
<reference value="/uf/1835"/>
</location>
<status value="completed"/>
<period>
<start value="2016-09-07T15:39:00"/>
<end value="2016-09-08T00:28:00"/>
</period>
</location>
<location>
<location>
<reference value="/uf/3650"/>
</location>
<status value="completed"/>
<period>
<start value="2016-09-08T00:28:00"/>
<end value="2016-09-11T16:35:00"/>
</period>
</location>
<serviceProvider>
<reference value="/uf/2407"/>
</serviceProvider>
</Encounter>
Where can I reference the specialist (endocrinologist) in the Encounter ?
If I understand correctly, the first would be identified as the referring practitioner, but the other is essentially just an "interested party" - someone who should be notified of the admission, the discharge and presumably should receive a copy of the discharge summary.
The concept of "interested party" isn't part of the value set for Encounter.participant.type, but the value set is extensible, so you're free to define your own code for that concept. It seems like a generally useful idea, so I'd encourage you to submit a change request (propose a change link at the bottom of each page in the spec) for us to add that to the specification for everyone.

Remove invalid XML after xmllint validation

I receive a large XML file and often the XML file do not validate to schema file.
Instead of droping the whole xml file I would like to remove the "invalid" content and save the rest of the XML file.
I'm using xmllint to validate the xml by this command:
xmllint -schema testSchedule.xsd testXML.xml
The XSD file (in this example named testSchedule.xsd):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.testing.dk" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="MasterData">
<xs:complexType>
<xs:sequence>
<xs:element name="Items">
<xs:complexType>
<xs:sequence>
<xs:element name="Item" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:integer" name="Id" minOccurs="1"/>
<xs:element type="xs:integer" name="Width" minOccurs="1"/>
<xs:element type="xs:integer" name="Height" minOccurs="0"/>
<xs:element type="xs:string" name="Remark"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And the XML file (In this example named testXML.xml):
<?xml version="1.0" encoding="ISO-8859-1" ?>
<MasterData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.testing.dk">
<Items>
<Item>
<Id>1</Id>
<Width>10</Width>
<Height>100</Height>
<Remark>This is OK</Remark>
</Item>
<Item>
<Id>2</Id>
<Width>20</Width>
<Height>200</Height>
<Remark>This is OK - But is missing Height a non mandatory field</Remark>
</Item>
<Item>
<Id>3</Id>
<Height>300</Height>
<Remark>This is NOT OK - Missing the mandatory Width</Remark>
</Item>
<Item>
<Id>4</Id>
<Width>TheIsAString</Width>
<Height>200</Height>
<Remark>This is NOT OK - Width is not an integer but a string</Remark>
</Item>
<Item>
<Id>5</Id>
<Width>50</Width>
<Height>500</Height>
<Remark>This is OK and the last</Remark>
</Item>
</Items>
</MasterData>
Then I get the this result of the xmllint command:
testXML.xml:18: element Height: Schemas validity error : Element '{http://www.testing.dk}Height': This element is not expected. Expected is ( {http://www.testing.dk}Width ).
testXML.xml:23: element Width: Schemas validity error : Element '{http://www.testing.dk}Width': 'TheIsAString' is not a valid value of the atomic type 'xs:integer'.
testXML.xml fails to validate
And that is all correct - There is two errors in the XML file.
Now I would like to have a tool of some kind to remove entry 3 and 4 so I end up with this result:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<MasterData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.testing.dk">
<Items>
<Item>
<Id>1</Id>
<Width>10</Width>
<Height>100</Height>
<Remark>This is OK</Remark>
</Item>
<Item>
<Id>2</Id>
<Width>20</Width>
<Height>200</Height>
<Remark>This is OK - But is missing Height a non mandatory field</Remark>
</Item>
<Item>
<Id>5</Id>
<Width>50</Width>
<Height>500</Height>
<Remark>This is OK and the last</Remark>
</Item>
</Items>
</MasterData>
Does anybody in here have a tool that can do this?
I'm currently using bash scripting and the xmllint.
I really hope somebody can help.
You can achieve that with this XSLT stylesheet, which you can run in any environment which supports XSLT 1.0 (most languages), using an command line tool such as xsltproc (libxslt) or Saxon, a browser or an online tool. Here is an example.
If you feed your original XML file as input to a XSLT transformer with the following stylesheet it will produce the result you have shown in your second XML:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:t="http://www.testing.dk">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="t:Item[t:Id and not(number(t:Id))]"/>
<xsl:template match="t:Item[t:Width and not(number(t:Width))]"/>
<xsl:template match="t:Item[t:Height and not(number(t:Height))]"/>
<xsl:template match="t:Item[not(t:Width)]"/>
<xsl:template match="t:Item[not(t:Id)]"/>
<xsl:template match="t:Item[not(t:Remark)]"/>
</xsl:stylesheet>
The first <xsl:template> block simply copies all nodes from the source tree to the result tree. It has lower precedence than the specific templates which match nodes by their name.
Since matches are done in XPath which requires namespace-qualified selectors, your default namespace was declared in the <xsl:stylesheet> opening tag and mapped to a prefix that was used to qualify the tag names.
Each template uses an XPath expression to test if a specific child element is present or not in Item, or if that child is present, if it is a number (according to the XSD).
I'm using XSLT 1.0, which is more widely supported and should be easier to find in your environment. But if you can use a XSLT 2.0 processor, you could use XSLT 2.0 features such as support for XSD types, and instead of comparing your values to number type, you could compare them to specific types like xsd:integer.
You can verify the transformation performed on your example XML by that stylesheet in this XSLT Fiddle.
If you create a XML document containing the code above and place it in a file named stylesheet.xsl you can run the transformation using xsltproc (which probably exists in your environment) using:
xsltproc stylesheet.xsl testXML.xml > fixedXML.xml

Magento soap error

I'm developing an iOS app that should integrate Magento e-commerce.
Actually I'm trying to put objects into the cart, when I try to do that my app sends to server this WSDL:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:Magento" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<call>
<sessionId xsi:type="xsd:string">e976c086bf862d23fcc98e59fb23b499</sessionId>
<resourcePath xsi:type="xsd:string">cart_product.add</resourcePath>
<args xsi:type="SOAP-ENC:Array">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">quoteId</key>
<value xsi:type="xsd:int">85</value>
</item>
<item>
<key xsi:type="xsd:string">products</key>
<value xsi:type="SOAP-ENC:Array">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">product_id</key>
<value xsi:type="xsd:string">1</value>
</item>
<item>
<key xsi:type="xsd:string">qty</key>
<value xsi:type="xsd:int">1</value>
</item>
</item>
</value>
</item>
</item>
</args>
</call>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I tried it with this extension for Google Chrome, when I try to run the WSDL
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>1</faultcode>
<faultstring>SQLSTATE[21000]: Cardinality violation: 1241 Operand should contain 1 column(s)</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
What's wrong in my request? Can anyone help me?
Solved now I'm sending this:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:Magento" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<call>
<sessionId xsi:type="xsd:string">38fd5af2c7fcfd55884b73ffded29225</sessionId>
<resourcePath xsi:type="xsd:string">cart_product.add</resourcePath>
<args xsi:type="SOAP-ENC:Array">
<item xsi:type="xsd:int">142</item>
<item xsi:type="SOAP-ENC:Array">
<item xsi:type="ns2:Map">
<item>
<key xsi:type="xsd:string">product_id</key>
<value xsi:type="xsd:string">2</value>
</item>
<item>
<key xsi:type="xsd:string">qty</key>
<value xsi:type="xsd:int">1</value>
</item>
</item>
</item>
</args>
</call>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I was formatting wrong the request, indeed, if you compare the 2 request you will see the difference: I was sending the key "quoteId", but it's not necessary.

SOAP Magento Error on Customer.Create

I am trying to create a customer from the Magja project and the AxisFault i am getting is a 100 "Customer email is required." . I am passing over the correct minimum required params from the 1.7 documentation. Long story my fault code is saying i am not including my email BUT it is clearly there (not putting the sensitive info on SO...so you just have to trust me :) ). Any Ideas?
Stack
org.eclipse.debug.core.DebugException: com.sun.jdi.ClassNotLoadedException: Type has not been loaded occurred while retrieving component type of array.
//soapclient line 208
result = sender.sendReceive(method) -> method variable
<mag:call xmlns:mag="urn:Magento" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-XML="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<sessionId>9be685563680f52c1ab5375bec545dfe</sessionId>
<resourcePath>customer.create</resourcePath>
<args SOAP-ENC:arrayType="xsd:ur-type[1]" xsi:type="SOAP-ENC:Array">
<item SOAP-ENC:arrayType="xsd:ur-type[1]" xsi:type="SOAP-ENC:Array">
<item xsi:type="SOAP-XML:Map">
<item>
<key xsi:type="xsd:string">email</key>
<value xsi:type="xsd:string">MY EMAIL</value>
</item>
<item>
<key xsi:type="xsd:string">password_hash</key>
<value xsi:type="xsd:string">4cb9c8a8048fd02294477fcb1a41191a</value>
</item>
<item>
<key xsi:type="xsd:string">group_id</key>
<value xsi:type="xsd:int">1</value>
</item>
<item>
<key xsi:type="xsd:string">store_id</key>
<value xsi:type="xsd:int">1</value>
</item>
<item>
<key xsi:type="xsd:string">lastname</key>
<value xsi:type="xsd:string">LName</value>
</item>
<item>
<key xsi:type="xsd:string">firstname</key>
<value xsi:type="xsd:string">Fname</value>
</item>
<item>
<key xsi:type="xsd:string">website_id</key>
<value xsi:type="xsd:int">1</value>
</item>
</item>
</item>
</args>
</mag:call>
//magentosoapclient line 215
throw axisFault (axisfault -> message)
<?xml version='1.0' encoding='utf-8'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>100</faultcode>
<faultstring>Customer email is required</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
You'll need to trace/log the data on the Magento end of things. Somehow email's getting lost and/or munged in the process. The PHP code that's called for a customer creation is at
#File: app/code/core/Mage/Customer/Model/Customer/Api.php
public function create($customerData)
{
$customerData = $this->_prepareData($customerData);
try {
$customer = Mage::getModel('customer/customer')
->setData($customerData)
->save();
} catch (Mage_Core_Exception $e) {
$this->_fault('data_invalid', $e->getMessage());
}
return $customer->getId();
}
and the specific exception being sent back to your SOAP client is at
#File: app/code/core/Mage/Customer/Model/Resource/Customer.php
protected function _beforeSave(Varien_Object $customer)
{
parent::_beforeSave($customer);
if (!$customer->getEmail()) {
throw Mage::exception('Mage_Customer', Mage::helper('customer')->__('Customer email is required'));
}
There's something about your client call and/or the specific Magento system you're using that makes Magento think there's no customer email set. A few calls to Mage::Log should set you on the right path.

Resources