How to add elements / attributes to xml file in karate [duplicate] - karate

I need to parse and print ns4:feature part. Karate prints it in json format. I tried referring to this answer. But, i get 'ERROR: 'Namespace for prefix 'xsi' has not been declared.' error, if used suggested xPath. i.e.,
* def list = $Test1/Envelope/Body/getPlan/planSummary/feature[1]
This is my XML: It contains lot many parts with different 'ns' values, but i have given here an extraxt.
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Header/>
<S:Body>
<ns9:getPlan xmlns:ns10="http://xmlschema.test.com/xsd_v8" xmlns:ns9="http://xmlschema.test.com/srv/SMO_v4" xmlns:ns8="http://xmlschema.test.com/xsd/Customer_v2" xmlns:ns7="http://xmlschema.test.com/xsd/Customer/Customer_v4" xmlns:ns6="http://schemas.test.com/eca/common_types_2_1" xmlns:ns5="http://xmlschema.test.com/xsd/Customer/BaseTypes_1_0" xmlns:ns4="http://xmlschema.test.com/xsd_v4" xmlns:ns3="http://xmlschema.test.com/xsd/Enterprise/BaseTypes/types/ping_v1" xmlns:ns2="http://xmlschema.test.com/xsd/common/exceptions/Exceptions_v1_0">
<ns9:planSummary xsi:type="ns4:Plan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns5:code>XPBSMWAT</ns5:code>
<ns5:description>Test Plan</ns5:description>
<ns4:category xsi:nil="true"/>
<ns4:effectiveDate>2009-11-05</ns4:effectiveDate>
<ns4:sharingGroupList>
<ns4:sharingCode>CAD_DATA</ns4:sharingCode>
<ns4:contributingInd>true</ns4:contributingInd>
</ns4:sharingGroupList>
<ns4:feature>
<ns5:code>ABC</ns5:code>
<ns5:description>Service</ns5:description>
<ns5:descriptionFrench>Service</ns5:descriptionFrench>
<ns4:poolGroupId xsi:nil="true"/>
<ns4:switchCode/>
<ns4:type/>
<ns4:dtInd>false</ns4:dtInd>
<ns4:usageCharge>0.0</ns4:usageCharge>
<ns4:connectInd>false</ns4:connectInd>
</ns4:feature>
</ns9:planSummary>
</ns9:getPlan>
</S:Body>
</S:Envelope>
This is the xPath i used;
Note: I saved above xml in a separate file test1.xml. I am just reading it and parsing the value.
* def Test1 = read('classpath:PP1/data/test1.xml')
* def list = $Test1/Envelope/Body/*[local-name()='getPlan']/*[local-name()='planSummary']/*[local-name()='feature']/*
* print list
This is the response i am getting;
16:20:10.729 [ForkJoinPool-1-worker-1] INFO com.intuit.karate - [print] [
"ABC",
"Service",
"Service",
"",
"",
"",
"false",
"0.0",
"false"
]
How can i get the same in XML?

This is interesting, I haven't seen this before. The problem was you have an attribute with a namespace xsi:nil="true" which is causing problems when you take a sub-set of the XML but the namespace is not defined anymore. If you remove it first, things will work.
Try this:
* remove Test1 //poolGroupId/#nil
* def temp = $Test1/Envelope/Body/getPlan/planSummary/feature
Another approach you could have tried is to do a string replace to remove troublesome stuff in the XML before doing XPath.
EDIT: added info on how to do a string replace using Java. The below will strip out the entire xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns4:Plan" part.
* string temp = Test1
* string temp = temp.replaceAll("xmlns:xsi[^>]*", "")
* print temp
So you get the idea. Just use regex.
Also see: https://stackoverflow.com/a/50372295/143475

Related

Unable to access the XML tag value using Karate.get() method

Unable to access the XML tag value using Karate.get() method
* def xml1 =
"""
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:QueryUsageBalance xmlns:ns2="http://www.mycompany.com/usage/V1">
<ns2:UsageBalance>
<ns2:LicenseId>12341234</ns2:LicenseId>
</ns2:UsageBalance>
</ns2:QueryUsageBalance>
</S:Body>
</S:Envelope>
"""
* def temp1 = karate.get('$xml1/S:Envelope/S:Body/ns2:QueryUsageBalance/ns2:UsageBalance/ns2:LicenseId')
* def result1 = temp1 ? 'yes' : 'no'
* print temp1
It's printing "no", seems unable to identify the XPATH. Could anyone please let me know what I am doing wrong here ?
I suggest you spend more time reading the docs and examples.
* def temp1 = $xml1/Envelope/Body/QueryUsageBalance/UsageBalance/LicenseId
* match temp1 == '12341234'

Karate: Match repeating element in xml

I'm trying to match a repeating element in a xml to karate schema.
XML message
* def xmlResponse =
"""
<Envelope>
<Header/>
<Body>
<Response>
<Customer>
<keys>
<primaryKey>1111111</primaryKey>
</keys>
<simplePay>false</simplePay>
</Customer>
<serviceGroupList>
<serviceGroup>
<name>XXXX</name>
<count>1</count>
<parentName>DDDDD</parentName>
<pendingCount>0</pendingCount>
<pendingHWSum>0.00</pendingHWSum>
</serviceGroup>
<serviceGroup>
<name>ZZZZZ</name>
<count>0</count>
<parentName/>
<pendingCount>3</pendingCount>
<pendingHWSum>399.00</pendingHWSum>
</serviceGroup>
</serviceGroupList>
</Response>
</Body>
</Envelope>
"""
I want to match each with following karate schema
Given def serviceGroupItem =
"""
<serviceGroup>
<name>##string</name>
<count>##string</count>
<parentName>##string</parentName>
<pendingCount>##string</pendingCount>
<pendingHWSum>##string</pendingHWSum>
</serviceGroup>
"""
This is how I tried
* xml serviceGroupListItems = get xmlResponse //serviceGroupList
* match each serviceGroupListItems == serviceGroupItem
But it doesn't work. Any idea how can I make it work
You have to match each serviceGroup.
* xml serviceGroupListItems = get xmlResponse //serviceGroupList
* match each serviceGroupListItems.serviceGroupList.serviceGroup == serviceGroupItem.serviceGroup

Convert xml response to payload

I have response coming like this -
<rsp stat="ok" version="1.0">
<result>
<tagObject>
<id>xx</id>
<tag_id>001</tag_id>
<type>Test</type>
<object_id>101</object_id>
<created_at>2013-10-09 11:41:45</created_at>
</tagObject>
<tagObject>
<id>xy</id>
<tag_id>002</tag_id>
<type>Test</type>
<object_id>102</object_id>
<created_at>2013-10-09 11:41:45</created_at>
</tagObject>
<tagObject>
<id>xz</id>
<tag_id>003</tag_id>
<type>Test</type>
<object_id>103</object_id>
<created_at>2013-10-09 11:43:44</created_at>
</tagObject>
</result>
</rsp>
Now I have to create a payload out of it, so that I can insert only <tag_id> and <object_id> into a database table.
Any suggestion on this? I was trying to work with Dataweave with Xpath3 but it did not work for me.
enter image description hereYou can convert Xml to Java map using dataweave
%dw 1.0
%output application/java
---
payload.rsp.result.*tagObject map ((tagObject , indexOfTagObject) -> {
tag_id: tagObject.tag_id as :string,
object_id: tagObject.object_id as :string
})
Out put: [{tag_id=001, object_id=101}, {tag_id=002, object_id=102}, {tag_id=003, object_id=103}].

How to extract urls from an xml using scrapy - XMLFeedSpider?

I have started using Scrapy recently and I'm trying to use the "XMLFeedSpider" to extract and load the pages that are in a xml page. But the problem is that it is returning an error: "IndexError: list index out of range".
I'm trying to collect and load all product pages that are at this address:"http://www.example.com/feed.xml"
My spider:
from scrapy.spiders import XMLFeedSpider
class PartySpider(XMLFeedSpider):
name = 'example'
allowed_domains = ['http://www.example.com']
start_urls = [
'http://www.example.com/feed.xml'
]
itertag = 'loc'
def parse_node(self, response, node):
self.logger.info('Hi, this is a <%s> node!: %s', self.itertag,''.join(node.extract()))
This is how your XML input starts:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>http://www.example.htm</loc></url>
<url><loc>http://www.example.htm</loc></url>
(...)
And there's acutally a bug in XMLFeedSpider when using (the default) iterator iternodes when the XML document uses a namespace. See this archived discussion in scrapy-users mailinglist.
This spider works, changing the iterator to xml, where you can reference a namespace, here http://www.sitemaps.org/schemas/sitemap/0.9 using the prefix n (it could be anything really), and using this namespace prefix for the tag to look for, here n:loc:
from scrapy.spiders import XMLFeedSpider
class PartySpider(XMLFeedSpider):
name = 'example'
allowed_domains = ['example.com']
start_urls = [
'http://www.example.com/example.xml'
]
namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
itertag = 'n:loc'
iterator = 'xml'
def parse_node(self, response, node):
self.logger.info('Hi, this is a <%s> node!: %s', self.itertag,''.join(node.extract()))

using LinkedIn API how to send HTML inside xml message

hi i am using the linkedin api to send invitations . in the message
<?xml version='1.0' encoding='UTF-8'?>
<mailbox-item>
<recipients>
<recipient>
<person path='/people/~'/>
</recipient>
<recipient>
<person path="/people/abcdefg" />
</recipient>
</recipients>
<subject>Congratulations on your new position.</subject>
<body>You're certainly the best person for the job!</body>
</mailbox-item>
in the <body> section i am trying to add some HTML .
like
<b>You're certainly the best person for the job!</b>
but the problem is it is shown as text as it is in the message recieved by the friend , instad of that i want to bold the message content . how can i do this . is there any configuration should be done .
i am using codeigniter
function send_messeges($access_token, $xml_atring) {
$profile_url = "http://api.linkedin.com/v1/people/~/mailbox";
$xml = '<?xml version="1.0" encoding="UTF-8" ?>
<mailbox-item>
<recipients>
' . $xml_atring . '
</recipients>
<subject>'.$this->send_subject.'</subject>
<body>'.$this->send_message.'</body>
</mailbox-item>';
$request = OAuthRequest::from_consumer_and_token($this->consumer, $access_token, "POST", $profile_url);
$request->sign_request($this->method, $this->consumer, $access_token);
$auth_header = $request->to_header("https://api.linkedin.com");
$response = $this->httpRequest($profile_url, $auth_header, "POST", $xml);
return $response;
}
please help . thanks in advance
If you want to wrap html in xml, you have to use a construct like this:
<xmltag><![CDATA[<b>html text</b>]]></xmltag>
But be careful to read the api docs:
https://developer.linkedin.com/documents/messaging-between-connections-api
body mailbox-item yes The body of the message. Cannot contain HTML.
Must be editable by the member sending the message.
This shows you cannot use html here.
You can however use basic string formatting such as newlines to have at least some paragraphs:
This is done via \n (escaped newline) within the string.