How to create a message containing xml prolog declaration - karate

I am trying to create some dynamic xml messages which will be sent to a service which expects xml. Said service also needs the xml prolog to be specified.
As I want to do a lot of manipulation on the xml I am reading it in a native xml type, however it seems that karate loses the xml prolog information during the conversion (on 0.9.5 and 0.9.6.RC3)
Feature: Example
# https://www.w3.org/TR/xml/#sec-prolog-dtd
Scenario: Example
Given def nativeXML =
"""
<?xml version="1.0" encoding="UTF-8" ?>
<greeting>Hello world</greeting>
"""
When string nativeToString = nativeXML
* print nativeToString
Then assert nativeToString.contains("encoding")
Is there a way to preserve the xml prolog?
Code to reproduce this can be found here: https://github.com/KostasKgr/karate-issues/blob/xml_prolog_to_string/src/test/java/examples/example.feature
Kind regards

Right now there is no other way but to append it manually, which IMO is simple enough. Karate removes it by default during a string conversion, because it gets in the way during Node operations.
Given def temp =
"""
<?xml version="1.0" encoding="UTF-8" ?>
<greeting>Hello world</greeting>
"""
* string body = temp
* def body = '<?xml version="1.0" encoding="UTF-8" ?>' + body
* print body
Then assert body.contains("encoding")

Related

Karate "match contains" for xml does not work like JSON [duplicate]

This question already has an answer here:
How to compare XML response with Json in Karate
(1 answer)
Closed 1 year ago.
I've noticed that "match contains" for checking if xml structure contains in another xml structure works differently than json counterpart. To give you an example :
* def expectedResult =
"""
<?xml version="1.0" encoding="UTF-8"?>
<response>
<id>1</id>
<id>2</id>
<id>3</id>
</response>
"""
* header Accept = xml
Given path 'some\path'
When method GET
Then status 200
## If response contains -
## <response><id>1</id></response>
## The following match will fail with -
## "actual and expected arrays are not the same size - 1:3"
And match response contains expectedResult
If it's a JSON structure, it will pass because 1 contains in the list of 1,2,3. But in XML, it's still checking array size. Is that how it suppose to work?
Update : This is not the same question as the other question. I'm trying to compare reference XML file that I have with XML structure being returned from the API. The question you linked to is comparing JSON reference file to XML response. So, that begs the question, in karate, do I have to convert my reference XML and response XML to json just to perform "contains"?
XML has some fundamental "shape" differences from JSON. I leave it to you to figure out, one of the challenges is the concept of a "root" tag, which JSON does not have. So they will not "match up" the way you may expect.
One tip - convert XML to JSON if in doubt. Here is an example:
* def expected =
"""
<?xml version="1.0" encoding="UTF-8"?>
<response>
<id>1</id>
<id>2</id>
<id>3</id>
</response>
"""
* json temp = $expected/response
* match temp.response.id == ['1', '2', '3']

How to set request body params in karate for soap request [duplicate]

I have the following xml:
<?xml version="1.0" encoding="utf-8"?>
<request>
<head>
<session-id>none</session-id>
</head>
<service name="test">
<function name="testFunc">
<guids>
<guid>#guid#</guid>
<guid>#guid#</guid>
</guids>
</function>
</service>
</request>
I have 2 test cases:
i want to test with single guid.
I want to test with 2 guids.
I created 2 separate xml for both the test cases and it worked.
The question here is how can i use a common xml?
Also i tried using remove but how do i remove single guid from the xml?
There is something called "embedded expressions" in Karate. Read the docs: https://github.com/intuit/karate#embedded-expressions
Example:
* def guids = <guids><guid>one</guid><guid>two</guid></guids>
* def body = <root>#(guids)</root>
Also refer this file, it has a lot of other examples and ideas for XML data-driven tests: xml.feature.

Karate: XML element changed to have empty namespace

when a xml message define like below, karate adds empty namespace to child element.
Karate feature
Feature: test xml
Scenario: test xml empty namespace
* def x =
"""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<validateEmailAddressRequest xmlns="anotherUri">
<request>
<email>some#domain.com</email>
</request>
</validateEmailAddressRequest>
</soapenv:Body>
</soapenv:Envelope>
"""
* print x
Output
16:39:17.009 [main] INFO com.intuit.karate - [print] <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<validateEmailAddressRequest xmlns="anotherUri">
<request xmlns="">
<email>some#domain.com</email>
</request>
</validateEmailAddressRequest>
</soapenv:Body>
</soapenv:Envelope>HTML report: (paste into browser to view) | Karate version: 0.9.4
if you look at the <request> element in the output it's now has the empty namespace where in feature does not.
That does create a problem when SOAP request hitting the server.
Do you know why this behaviour and how can I override it?
This is very interesting and I just tried this and don't see this problem at all. My guess is that the version of the Java runtime you are using may have some bug in the XML libraries. Can you do us a favor and replicate this problem using this process ? https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue - and make sure you specify the exact OS + Java version.
Meanwhile as a workaround, you can do this - convert the XML to a string, do a Java String.replace() and then re-convert:
* xmlstring x = x
* xml x = x.replace(' xmlns=""', '')
* print x
EDIT - here is the issue that provides a solution (available in 1.2.0 onwards) https://github.com/karatelabs/karate/issues/1587
* configure xmlNamespaceAware = true

XML parsing error in SQL Server stored procedure

I want to parse the below XML in a SQL Server stored procedure and update some tables based on this XML. I have implemented the same using OPENXML but now there is one more line added to the beginning of the XML, because of which am getting unexpected errors. Is it possible to somehow skip the first tag alone while parsing
Parsing code :
set #Lead= (select lead
from openxml(#DOCHANDLE,'/DBO.TBLLEADS',2) with (lead INT 'LEAD'))`
XML here:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LEADS>
<LEAD>6680299</LEAD>
<JOBNO>50919</JOBNO>
<BEGINDATE>4-04-2013</BEGINDATE>
<ENDDATE>04/14/2013</ENDDATE>
</LEADS>
Well, not the most elegant solution, but will get it back to working:
Before you prepare your XML document, run this statement on the variable containing the XML:
SET #XMLVariable = REPLACE(#XMLVariable, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>', '')
Basically you're leveraging the REPLACE function to replace the unnecessary header string with nothing.

SimpleXML save tag content as variable

OK I've been working with tag attributes up to now, but what if I want to save the actual contents of a tag as a variable, how would I do that?
For instance, in the example below, how would I save 'John' to a variable?
<person>
<name>John</name>
</person>
Thanks!
You're talking about SimpleXML in PHP?
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8" ?><person><name>John</name></person>');
$john = $xml->name ;
echo $john ;
The reason we use $xml->name in our example rather than $xml->person->name is that SimpleXML will assume the root element (worth keeping in mind :). In a real example the XML would have a different root element, with perhaps several <person> elements, which you then could get by array notation, as in ;
$james = $xml->person[4]->name ;
A more powerful way is to use Xpath which is worth looking into for better dealing with complex XML ;
$john = $xml->xpath ( 'person/name' ) ;
Using PHP, you can do it in this way:-
<?php
$xmlstr = <<<XML
<person>
<name>John</name>
</person>
XML;
$xml = new SimpleXMLElement($xmlstr);
$name_person = $xml->name;
// If you are unsure about the node string, then it's best to write it as:-
$name_person = $xml->{'name'};
/**
* This above statement will take care if the node string contain characters not permitted under PHP's naming convention (e.g. the hyphen) can be accomplished by encapsulating the element name within braces and the apostrophe.
*/
?>
More info is available here.
Hope it helps.