How to modify the xml on onRequestscript() in SOAP UI - web-services

Here is my code which i wrote in onRequestscript
def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)
path = "D:\\Service\\something2.xml";
log.info("path = "+ path);
if (mockRequest.method == "POST" )
{
mockRunner.returnFile( mockRequest.httpResponse, new File(path))
return new com.eviware.soapui.impl.wsdl.mock.WsdlMockResult(mockRequest)
}
But this script changes my XML entirely... I want to modify an existing XML(something.xml)..
i was actually Not able to modify the xml so i thought of changinf the xml instead.But according to my business logic its wrong... So can any one help me to modify the xml
in onRequestscript....
XML like
<Something>
<Data1>
<value>100</value>
<Data1>
<Data2>
<value>200</value>
<Data2>
</Something>
to a modified like this
<Something>
<Data1>
<value>101</value>
<Data1>
<Data2>
<value>201</value>
<Data2>
</Something>

You can use XmlSlurper to parse and update values from XML file. Then generate a string from updated XML and set it to the response of your mock service.
I use free SoapUI 3.6.1 but it seems that its output object differs from your example. Revise the code for your needs.
// get and parse XML file content
path = "D:\\Service\\something2.xml";
def doc = new XmlSlurper().parse(path)
// update values
doc.Data1.value[0] = 101
doc.Data2.value[0] = 201
// generate and return XML string as service response
import groovy.xml.StreamingMarkupBuilder
def result = new StreamingMarkupBuilder().bind{ mkp.yield doc }.toString()
mockResponse.setResponseContent(result)

Related

How to enable schema validation in saxon api (.net)

I have downloaded the latest 9ee version of saxon api for dotnet.
I've got a simple program that transforms an xml from an xslt.
it works for simple xslts, but I cannot seem to see how to enable schema validation (of the xslt document).
here is my C# (thanks to How to use XSLT 3.0 using Saxon-HE 9.8 in .NET)
public static string TransformXml(string xmlData, string xslData)
{
var xsltProcessor = new Processor(true);
var documentBuilder = xsltProcessor.NewDocumentBuilder();
documentBuilder.BaseUri = new Uri("file://");
var xdmNode = documentBuilder.Build(new StringReader(xmlData));
var xsltCompiler = xsltProcessor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new StringReader(xslData));
var xsltTransformer = xsltExecutable.Load();
xsltTransformer.InitialContextNode = xdmNode;
var results = new XdmDestination();
xsltTransformer.Run(results);
return results.XdmNode.OuterXml;
}
here is my xslt (taken largely from "mastering xslt" Doug Tidwell)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="text" />
<xsl:import-schema schema-location="file:///C:/Users/m_r_n/source/repos/SaxonEEExample/ValidateXslt/po1.xsd" />
<xsl:template match="schema-element(PurchaseOrder)">
<xsl:for-each select="item">
<xsl:value-of select="#id" />: <xsl:value-of select="title" />
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="*">
<xsl:message terminate="yes">Source document is not a purchase order
</xsl:message>
</xsl:template>
</xsl:stylesheet>
when I run it, I get
"Source document is not purchase order"....
If I remove the "schema-element" function, then I get the desired
100: Water for Elephants
101: Glass Castle: A Memoir
200: 5 Amp Electric plug
my hunch is the xslt is correct, but I'm missing some setting on API (to be fair the saxon examples, don't include this sort of thing)
edit
actually to be honest, I want to be able to do 2 things, 1 validate an xslt against an input schema (import-schema) AND execute an XSLT against an xslt with these constructs, as 2 seperate operations.
edit
so taking the feedback from Michael Kay in the comments.
I've gone back to the saxon examples, and borrowed the validator example.
Rather than validating an instance document, I've tried to validate the XSLT itself.
var samplesDir = new Uri(AppDomain.CurrentDomain.BaseDirectory);
Processor processor = new Processor(true);
processor.SetProperty("http://saxon.sf.net/feature/timing", "true");
processor.SetProperty("http://saxon.sf.net/feature/validation-warnings", "false"); //Set to true to suppress the exception
SchemaManager manager = processor.SchemaManager;
manager.XsdVersion = "1.1";
manager.ErrorList = new List<StaticError>();
Uri schemaUri = new Uri(samplesDir, "po1.xsd");
try
{
manager.Compile(schemaUri);
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine("Schema compilation failed with " + manager.ErrorList.Count + " errors");
foreach (StaticError error in manager.ErrorList)
{
Console.WriteLine("At line " + error.LineNumber + ": " + error.Message);
}
return;
}
// Use this to validate an instance document
SchemaValidator validator = manager.NewSchemaValidator();
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Ignore;
String inputFileName = new Uri(samplesDir, "po.xsl").ToString();
XmlReader xmlReader = XmlReader.Create(inputFileName, settings);
validator.SetSource(xmlReader);
Console.WriteLine("Validating input file " + inputFileName);
validator.ErrorList = new List<ValidationFailure>();
XdmDestination psvi = new XdmDestination();
validator.SetDestination(psvi);
try
{
validator.Run();
}
catch (Exception e)
{
Console.WriteLine(e);
Console.WriteLine("Instance validation failed with " + validator.ErrorList.Count + " errors");
foreach (ValidationFailure error in validator.ErrorList)
{
Console.WriteLine("At line " + error.GetLineNumber() + ": " + error.GetMessage());
}
return;
}
the result on the console is
Loading schema document file:///C:/Users/m_r_n/source/repos/SaxonEEExample/ValidateXslt/bin/Debug/po1.xsd
Using parser org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser
Found registry key at HKEY_LOCAL_MACHINE\Software\Saxonica\SaxonEE-N\Settings
Software installation path: c:\Program Files\Saxon\SaxonEE9.9N
Finished loading schema document file:///C:/Users/m_r_n/source/repos/SaxonEEExample/ValidateXslt/bin/Debug/po1.xsd
Validating input file file:///C:/Users/m_r_n/source/repos/SaxonEEExample/ValidateXslt/bin/Debug/po.xsl
One validation error was reported: Cannot validate <Q{.../Transform}stylesheet>: no element declaration available
Instance validation failed with 1 errors
At line 2: Cannot validate <Q{.../Transform}stylesheet>: no element declaration available
There are two approaches.
You can use xsl:import-schema to load the schema, but then it's only the XSLT processor that knows about the schema, so the input document needs to be built and validated under the control of XSLT. If you set SchemaValidationMode on the XsltTransformer, and supply the input to the XsltTransformer as an unparsed Stream, then it will be parsed with schema validation.
The alternative is to use the DocumentBuilder as you are doing, and make sure that it does the validation. To do this, you need to load the schema using SchemaManager.Compile, then create a SchemaValidator from this schema, and supply this to the DocumentBuilder.
To be fair Michael Kay answered the question I'm just putting this in for completeness, and this is pretty much the minimal example.
This will fail (with an exception) during "compile", if the XSLT is referencing an invalid (I used "PurchaseOrder1") node that isnt referenced in the schema.
var samplesDir = new Uri(AppDomain.CurrentDomain.BaseDirectory);
// Create a Processor instance.
Processor processor = new Processor(true);
// Create a transformer for the stylesheet.
//Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "poNoValidation.xsl")).Load30();
Xslt30Transformer transformer = processor.NewXsltCompiler().Compile(new Uri(samplesDir, "po.xsl")).Load30();
// Create a serializer, with output to the standard output stream
Serializer serializer = processor.NewSerializer();
serializer.SetOutputWriter(Console.Out);
// Transform the source XML and serialize the result document
transformer.SchemaValidationMode = SchemaValidationMode.Strict;
transformer.ApplyTemplates(File.OpenRead("po.xml"), serializer);

how to save a xml list from response to a csv file in JMeter

one of my tests uses a Loop Controller, CSV Data Set Config and an If Controller to iterate through a csv list to do one request with several parameters defined in an csv file.
I want to change this testcase to use a list of parameters that i get from an GET response in an xml format.
for example using this xml list: http://www.w3schools.com/xml/cd_catalog.xml
now i want to iterate through all < TITLE > values.
i tried to save the response with the 'Save Responses to a file' Listener and then use a BeanShell Listener to read the file and transform it to a csv list which contains only the < TITLE > values. but i'm not sure how to to this transformation part in the BeanShell Listener.
import org.apache.jmeter.services.FileServer;
import org.apache.commons.io.FileUtils;
File xmlFile = new File(FileServer.getFileServer().getBaseDir()+"/resources/data/csv/response1.xml", "UTF-8");
String fileData = FileUtils.readFileToString(xmlFile);
fileData = fileData.replaceAll("<?xml version="1.0" encoding="UTF-8"?>", "");
fileData = fileData.replaceAll("<CATALOG>", "");
//...
FileUtils.writeStringToFile(xmlFile, fileData);
/*
f = new FileOutputStream(FileServer.getFileServer().getBaseDir()+"/resources/data/csv/parameterlist.csv", true);
p = new PrintStream(f);
p.println(fileData);
p.close();
f.close();
*/
there must be some solution using regex, xpath or XSL transformation on all < TITLE > elements or is there an easier way that i didn't thought of?
found a different and easier method that works for my purpose:
Get Request to get the xml list.
add XPath Extractor
Reference Name: 'titles'
XPAth query: '//title'
ForEach Controller
Input variable prefix: 'titles'
Output variable name: 'title'

Create sub-tags in Matlab Soap request

I am developing a SOAP client in Matlab for connection a Web Service. What I am doing is the following script:
createClassFromWsdl('http://192.168.107.239/WSDL/v4.0/iLON100.wsdl')
obj = iLON100
methods(obj)
With the next result:
Methods for class iLON100:
Clear Get List Set display
Delete InvokeCmd Read Write iLON100
Then, I am editing for example the method List in order to request the list of Items for the service. The dot m file is:
% Build up the argument lists.
values = { '','//Item[#xsi:type="Dp_Cfg"]'};
names = { 'iLonItem','xSelect'};
types = {};
% Create the message, make the call, and convert the response into a variable.
soapMessage = createSoapMessage('http://wsdl.echelon.com/web_services_ns/ilon100/v4.0/message/',
'List', values, names, types, 'document');
I have also a SOAP tester from the vendor of the device. Then, if I compare both XML requests, they differ as you can see in the next example (firstly the original request and secondly the Matlab one):
<SOAP-ENV:Body>
<List xmlns="http://wsdl.echelon.com/web_services_ns/ilon100/v4.0/message/">
<iLonItem>
<xSelect>
//Item[#xsi:type="Dp_Cfg"]
</xSelect>
</iLonItem>
</List>
</SOAP-ENV:Body>
<soap:Body soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<List xmlns="http://wsdl.echelon.com/web_services_ns/ilon100/v4.0/message/">
<iLonItem/>
<xSelect>Item</xSelect>
</List>
</soap:Body>
As you can observe, the tags are not included as sub-tags. I would like to know how to do it and generate the same structure of XML for sending the SOAP request correctly.
Thank you so much,
At the end, I have solved it by creating a structure as follows:
myStruct = struct('iLonItem',struct('xSelect','//Item[#xsi:type="Dp_Cfg"]'))
This structure is inserted into "values" and the method's name "iLONItem".

Saxon XSLT .Net Transformation: What to give in BaseURI when xml and xsl both are passed as strings

This is the code I have for Saxon Transformation of XSLT files which accepts xml and xslt and returns a transformed string. I can have either xsl 1.0 or 2.0 get processed through this function.
DocumentBuilder requires a BaseURI, even if I don't have any file format. I have provided "c:\\" as the BaseURI, inspite I have nothing to do with this directory.
Is there any better way to achieve this thing or write this function?
public static string SaxonTransform(string xmlContent, string xsltContent)
{
// Create a Processor instance.
Processor processor = new Processor();
// Load the source document into a DocumentBuilder
DocumentBuilder builder = processor.NewDocumentBuilder();
Uri sUri = new Uri("c:\\");
// Now set the baseUri for the builder we created.
builder.BaseUri = sUri;
// Instantiating the Build method of the DocumentBuilder class will then
// provide the proper XdmNode type for processing.
XdmNode input = builder.Build(new StringReader(xmlContent));
// Create a transformer for the stylesheet.
XsltTransformer transformer = processor.NewXsltCompiler().Compile(new StringReader(xsltContent)).Load();
// Set the root node of the source document to be the initial context node.
transformer.InitialContextNode = input;
StringWriter results = new StringWriter();
// Create a serializer.
Serializer serializer = new Serializer();
serializer.SetOutputWriter(results);
transformer.Run(serializer);
return results.ToString();
}
If you think that the base URI will never be used (because you never do anything that depends on the base URI) then the best strategy is to set a base URI that will be instantly recognizable if your assumption turns out to be wrong, for example "file:///dummy/base/uri".
Choose something that is a legal URI (C:\ is not).

XML Getting attibute value of a Node

I am using XML DOM API in C++ to parse an XML file. I can't find any method to get the attribute value in a node element.
For example, in the following xml
<test>
<fruit count="10">
...
...
</fruit>
<test>
I need to get the count string("10") using XML APIs. Can anybody help me with some code snippets.
Use DOM Parser API to get attribute value count.
Refer below sample code:
//code to perform some process for parsing the input file and get rootElement
DOMNodeList* fruitNodes= rootElement->getElementsByTagName(XMLString::transcode("fruit"));
DOMNode* node = fruitNodes->item(0);
DOMElement* fruitElement = dynamic_cast <xercesc::DOMElement*>(node);
const XMLCh* attrValue = fruitElement->getAttribute(XMLString::transcode("count"));
you can get value 10 from attrValue using: string(XMLString::transcode(attrValue))
Based on http://msdn.microsoft.com/en-us/library/windows/desktop/ms754523(v=vs.85).aspx
Try something like:
pXMLDomNodeList = pXMLDocElement->selectNodes("/test/fruit/#count");