Karate: XML element changed to have empty namespace - karate

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

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 create a message containing xml prolog declaration

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")

karate does not match xml with namespaces

I have two xml messages with namespaces which are essentially the same xml but match says they are not same.
Please look at the feature below.
xmlString1 and xmlString2 are essentially same xmls. Only the namespace prefix is different. I am not sure if match matches xml equality?
Is there a way I can achieve xml match with namespaces?
Feature: Test xml match
Scenario: test xml match with namespaces
* def xmlString1 =
"""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:b="anotherUri">
<soapenv:Header/>
<soapenv:Body>
<b:validateEmailAddressRequest>
<request>
<email>some#domain.com</email>
</request>
</b:validateEmailAddressRequest>
</soapenv:Body>
</soapenv:Envelope>
"""
* def xmlString2 =
"""
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="anotherUri">
<soapenv:Header/>
<soapenv:Body>
<a:validateEmailAddressRequest>
<request>
<email>some#domain.com</email>
</request>
</a:validateEmailAddressRequest>
</soapenv:Body>
</soapenv:Envelope>
"""
* xml xml1 = xmlString1
* xml xml2 = xmlString2
* match xml1 == xml2
16:49:04.363 [main] ERROR com.intuit.karate - assertion failed: path: /soapenv:Envelope/_/soapenv:Body, actual: '<soapenv:Body><b:validateEmailAddressRequest><request><email>some#domain.com</email></request></b:validateEmailAddressRequest></soapenv:Body>', expected: '<soapenv:Body><a:validateEmailAddressRequest><request><email>some#domain.com</email></request></a:validateEmailAddressRequest></soapenv:Body>', reason: all key-values did not match, expected has un-matched keys: [a:validateEmailAddressRequest]
xml-match.feature:34 - path: /soapenv:Envelope/_/soapenv:Body, actual: '<soapenv:Body><b:validateEmailAddressRequest><request><email>some#domain.com</email></request></b:validateEmailAddressRequest></soapenv:Body>', expected: '<soapenv:Body><a:validateEmailAddressRequest><request><email>some#domain.com</email></request></a:validateEmailAddressRequest></soapenv:Body>', reason: all key-values did not match, expected has un-matched keys: [a:validateEmailAddressRequest]
You are welcome to contribute a fix for this. Meanwhile you can do this. Note that you don't need to convert to xml, def xml1 is sufficient even if you use the triple-quote multi-line form. You may be confused with text.
* xmlstring xml2 = xml2
* xml xml2 = xml2.replaceAll('(</?)a:', '$1b:').replace('xmlns:a', 'xmlns:b')
* match xml1 == xml2

How to validate part of message in WSOESB and choose first?

Here is how it works.
I do have dss service that returns message of format
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dss="https://rmis33.r-mis.ru/services/dss">
<soapenv:Header/>
<soapenv:Body>
<dss:Requests>
<dss:Request>...</dss:Request>
<dss:Request>...</dss:Request>
<dss:Request>...</dss:Request>
....
<dss:Request>...</dss:Request>
</dss:Requests>
</soapenv:Body>
</soapenv:Envelope>
I have to split message on Request element and validate it, then choose first that pass validation over XSD.
It is hard to do on database level because it has a lot of elements(sub-elements) and XSD was already provided.
You can use validate mediator to validate XML messages against XML schema.There is a complete sample which demonstrates validating messages.

Web Service returning definition of response with initial value set

So I have a simple webservice that has an input of a userid and gets a flag from a sql database (initially set to '1').
However, when I query a user with the default value of the flag (which I set to 1 in SQL Server), I get the following response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<result xsi:type="ns1:getPWFlagResponse" xsi:nil="1" xmlns:ns1="<NamespaceURL>"/>
</soapenv:Body>
</soapenv:Envelope>
However, if I change the value of the flag, I Get the correct response for all other requests:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<result>
<result>1</result>
</result>
</soapenv:Body>
</soapenv:Envelope>
(Same for result of 0 ).
I thought that it could be that I didn't initialize something at first, however if I don't set an initial value on the PWResetFlag column in the table the webService comes back with the correct response.
Is this something with SQL server and setting default values or something on my end?
Thanks
Just wanted to update the question in case anyone else has had similar problems, but I have found the root source of my problem. I was using TOAD for sql server to do my table alterations, but when I went on to the actual server and into the database, the flag was set to NULL as a default value despite me altering it to not accept nulls and applying a default value of 1.
I did the alterations directly in SQL Server on the machine which correctly applied the default value and now my webservice is working perfectly!
Thanks