Scala XML transformation with Rewrite rules - scala

I have a XML template with some fields predefined in it. I want to build new XML based on it template with new Value values using RewriteRules.
ex.
template:
val template = <xml>
<Persons>
<Name>Persons</Name>
<Person>
<FullName>
<Name>Name of the field</Name>
<Value></Value>
</FullName>
<LastName>
<Name>Name of the field</Name>
<Value></Value>
</LastName>
</Person>
</Persons>
</xml>
case class Person(fullName: String, lastName: String)
val persons = Seq(Person("John Smith", "Smith"), Person("Bob Saver", "Saver"))
output should be:
<xml>
<Persons>
<Name>Persons</Name>
<Person>
<FullName>
<Name>Name of the field</Name>
<Value>John Smith</Value>
</FullName>
<LastName>
<Name>Name of the field</Name>
<Value>Smith</Value>
</LastName>
</Person>
<Person>
<FullName>
<Name>Name of the field</Name>
<Value>Bob Saver</Value>
</FullName>
<LastName>
<Name>Name of the field</Name>
<Value>Saver</Value>
</LastName>
</Person>
</Persons>
</xml>
Is it possible to do with RewriteRules?

You do not need RewriteRules for this purposes. You can define variables in your xml template.
scala> def template(id: String = "defaultValue can be here") = <someXml>{id}</someXml>
template: (id: String)scala.xml.Elem
scala> template("person")
res4: scala.xml.Elem = <someXml>person</someXml>
scala> template("person2")
res5: scala.xml.Elem = <someXml>person2</someXml>
otherwise
Scala - replace xml element with specific text

Related

Spark parse XML with multiple types

I have the following XML and I am using https://mvnrepository.com/artifact/com.databricks/spark-xml to import as dataframe
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<property key="id">1</property>
<property key="fname">x</property>
<property key="lname">y</property>
<property key="address">
<address>
<street>999 abc WAY</street>
<zip>9999</zip>
</address>
</property>
</row>
<row>
<property key="id">2</property>
<property key="fname">a</property>
<property key="lname">b</property>
</row>
</root>
I use the following logic to import as Spark DataFrame
val testData = spark.read
.option("rootTag", "root")
.option("rowTag", "row")
.XML("./test.xml")
But o/p
testData.show(false)
+--------------------------------------------------------------------------------------------------+
|property |
+--------------------------------------------------------------------------------------------------+
|[{null, id, null}, {null, fname, null}, {null, lname, null}, {null, address, {999 abc WAY, 9999}}]|
|[{null, id, null}, {null, fname, null}, {null, lname, null}] |
+--------------------------------------------------------------------------------------------------+
without address node in XML
scala> testData.show(false)
+---------------------------------+
|property |
+---------------------------------+
|[{1, id}, {x, fname}, {y, lname}]|
|[{2, id}, {a, fname}, {b, lname}]|
+---------------------------------+
How to parse in a situation where a node has multiple types of values. One is text and other is the address object.

Verifying Signed Xml Generated From Java In NET

I have the below XML,
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Response xmlns="http://www.site.ae/g">
<Message xml:id="message">
<Header>
<Service>Read</Service>
<Action>SomeAction</Action>
</Header>
<Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SomeDataType">
<Status>Success</Status>
<Data>
<Id>123</Id>
</Data>
</Body>
</Message>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<Reference URI="#message">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<DigestValue>SomeValue</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
SomeValue
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>
SomeValue
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</Response>
The above XML genereted from a java application. The java application team provided us 3 certificate to verify the above xml. I have created 3 objects in C#,
var clientCert = new X509Certificate2("clientCert.cer");
var intermediateCert = new X509Certificate2("intermediateCert.cer");
var rootCert = new X509Certificate2("rootCert.cer");
One is root, second one is intermediate and third one is certificate. I have created the below code,
var xmlDoc = new XmlDocument();
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load("above.xml");
bool result = VerifyXml(xmlDoc, clientCert);
private static Boolean VerifyXml(XmlDocument Doc, X509Certificate2 Key)
{
// Create a new SignedXml object and pass it
// the XML document class.
var signedXml = new System.Security.Cryptography.Xml.SignedXml(Doc);
// Find the "Signature" node and create a new XmlNodeList object.
XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");
// Throw an exception if no signature was found.
if (nodeList.Count <= 0)
{
throw new CryptographicException("Verification failed: No Signature was found in the document.");
}
// Though it is possible to have multiple signatures on
// an XML document, this app only supports one signature for
// the entire XML document. Throw an exception
// if more than one signature was found.
if (nodeList.Count >= 2)
{
throw new CryptographicException("Verification failed: More that one signature was found for the document.");
}
// Load the first <signature> node.
signedXml.LoadXml((XmlElement)nodeList[0]);
// Check the signature and return the result.
return signedXml.CheckSignature(Key, true);
}
But the above code result is always return false. Is there is something I am missing? Is .NET support verifying the xml generated from java?
Got Answer from
Verify SignatureValue And DigestValue Using Sha256 RSA

How do i use a testng test names inside a function for an if condition

Consider i have three testng xml files available.How do i use it's names or the variables in it for a validation inside a function . i have to use an if condition inside a function to run certain lines if a particular testng xml file has been run
The below sample shows how you can access the <suite> name or even the current <test> name, and also the parameters defined at either the <suite> level or at <test> level.
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.Test;
import org.testng.xml.XmlSuite;
import org.testng.xml.XmlTest;
public class SampleTestClass {
#Test
public void sampleTestMethod() {
ITestResult result = Reporter.getCurrentTestResult();
XmlTest xmltest = result.getTestContext().getCurrentXmlTest();
XmlSuite xmlsuite = xmltest.getSuite();
System.err.println("The <test> name is : " + xmltest.getName());
System.err.println("The <suite> name is :" + xmlsuite.getName());
System.err.println("Parameters defined at <test> level");
xmltest
.getLocalParameters()
.forEach(
(key, value) -> System.err.println(String.format("[Key: %s, Value: %s]", key, value)));
System.err.println("Parameters defined at <suite> level");
xmlsuite
.getParameters()
.forEach(
(key, value) -> System.err.println(String.format("[Key: %s, Value: %s]", key, value)));
}
}
Below is the suite xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Question_53317518_suite" parallel="false" verbose="2">
<parameter name="suite_param_one" value="a"/>
<parameter name="suite_param_two" value="b"/>
<parameter name="suite_param_three" value="c"/>
<test name="Question_53317518_test">
<parameter name="test_param_one" value="1"/>
<parameter name="test_param_two" value="2"/>
<parameter name="test_param_three" value="3"/>
<classes>
<class name="com.rationaleemotions.stackoverflow.qn53317518.SampleTestClass"/>
</classes>
</test>
</suite>
Here's the execution output
...
... TestNG 7.0.0-beta1 by Cédric Beust (cedric#beust.com)
...
The <test> name is : Question_53317518_test
The <suite> name is :Question_53317518_suite
Parameters defined at <test> level
[Key: test_param_two, Value: 2]
[Key: test_param_three, Value: 3]
[Key: test_param_one, Value: 1]
Parameters defined at <suite> level
[Key: suite_param_two, Value: b]
[Key: suite_param_one, Value: a]
[Key: suite_param_three, Value: c]
PASSED: sampleTestMethod
===============================================
Question_53317518_test
Tests run: 1, Failures: 0, Skips: 0
===============================================
===============================================
Question_53317518_suite
Total tests run: 1, Passes: 1, Failures: 0, Skips: 0
===============================================
Process finished with exit code 0

Kie Workbench Execute Rules

May be this question has been asked number of times but I could not figure out the actual solution by going through them. I have a decision table in KIEWorkbench which takes the input from one fact and sets it into another fact. I am trying to call the rules by invoking the endpoint: http://localhost:8085/kie-server-6.4.0.Final-ee7/services/rest/server/containers/instances/pocResult
In the header, I have set the Content-Type as application/xml.
<batch-execution lookup="ksession">
<insert out-identifier="Subject">
<demo.pocFindResult.Subject>
<bCode> ABC</bCode>
<bGCode>XY</bGCode>
<pCode>L0001</pcode>
<subjectType>CA</subjectType>
</demo.pocFindResult.Subject>
</insert>
<fire-all-rules />
<get-objects out-identifier="Result">
<demo.pocFindResult.result/>
</get-objects>
My Decision table is as below:
package demo.pocFindResult;
//from row number: 1
rule "Row 1 findrules"
ruleflow-group "fire-rules"
dialect "java"
lock-on-active true
no-loop true
when
sub : Subject( bCode == "ABC" , bGCode == "XY" , subjectType == "CA" , pCode == "L0001" )
then
Result rs = new Result();
rs.setResultStartDate( "*TODAY" );
rs.setResultEndDate( "*YEAREND" );
rs.setResultContentStartDate( "*TODAY" );
rs.setResultContentEndDate( "*YEAREND" );
insert( rs );
end
How can I get the Result object as the response? Here is my response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response type="SUCCESS" msg="Container pocResult successfully called.">
<execution-results>
<results>
<item key="Subject">
<value xsi:type="jaxbListWrapper" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<type>LIST</type>
</value>
</item>
</results>
<facts>
<item key="Subject"/>
</facts>
</execution-results>
</response>
I want the result object with the dates set.
What is the response you get?
I would firstly try to place fire-all-rules tag after your return object. Otherwise, I would try:
<batch-execution lookup="ksession">
<insert out-identifier="Subject">
<demo.pocFindResult.Subject>
<bCode> ABC</bCode>
<bGCode>XY</bGCode>
<pCode>L0001</pcode>
<subjectType>CA</subjectType>
</demo.pocFindResult.Subject>
</insert>
<insert out-identifier="Result" return-object="true" entry-point="DEFAULT">
<demo.pocFindResult.result/>
</insert>
<fire-all-rules/>
</batch-execution>
I am using JBPM 7.0.0-SNAPSHOT and got the same result as yours. When I used the same rules in 6.2.0.Final, I had result back.
EDIT:
The key problem is the header:
Authorization:Basic YWRtaW46YWRtaW4=
Content-Type:application/xml ,
Then I added another header:
"X-KIE-ContentType : XSTREAM"
<batch-execution lookup="defaultKieSession">
<insert return-object="true">
<com.bp.PageContext>
<ID>AID</ID>
</com.bp.PageContext>
</insert>
<insert out-identifier="Group" return-object="true">
<com.bp.GroupData>
</com.bp.GroupData>
</insert>
<insert out-identifier="ERR" return-object="true">
<com.bp.ErrorMessage/>
</insert>
<fire-all-rules/>
<get-objects/>
</batch-execution>
I've got the result back:
<org.kie.server.api.model.ServiceResponse>
<type>SUCCESS</type>
<msg>Container bpcontainr successfully called.</msg>
<result class="execution-results">
<result identifier="Group">
<com.bp,GroupData>
<Code>TEST,QA</Code>
</com.bp.GroupData>
</result>
<result identifier="ERR">
<com.bp.ErrorMessage/>
</result>
<fact-handle identifier="Group" external-form="0:8:567620710:567620710:8:DEFAULT:NON_TRAIT:com.bp.GroupData"/>
<fact-handle identifier="ERR" external-form="0:9:1581854082:1581854082:9:DEFAULT:NON_TRAIT:com.bp.ErrorMessage"/>
</result>
</org.kie.server.api.model.ServiceResponse>

How to read an ODS document?

My goal is to simply read an ODS file that was created with Libre Office - Calc.
Using org.apache.odftoolkit:odfdom-java:0.8.8-incubating I open the ODS file and convert the content to scala xml as follows:
val doc = OdfSpreadsheetDocument.loadDocument(classOf[OdfTest].getResourceAsStream("/test.ods"))
val dom: OdfContentDom = doc.getContentDom
val xml = XML.loadString(dom.toString)
This produces the following xml:
<office:document-content office:version="1.2"
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dom="http://www.w3.org/2001/xml-events"
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
xmlns:drawooo="http://openoffice.org/2010/draw"
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
xmlns:grddl="http://www.w3.org/2003/g/data-view#"
xmlns:math="http://www.w3.org/1998/Math/MathML"
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2"
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc"
xmlns:ooow="http://openoffice.org/2004/writer"
xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0"
xmlns:rpt="http://openoffice.org/2005/report"
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:tableooo="http://openoffice.org/2009/table"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<office:scripts></office:scripts>
<office:font-face-decls>
<style:font-face style:font-family-generic="swiss" style:font-pitch="variable" style:name="Liberation Sans"
svg:font-family="'Liberation Sans'"></style:font-face>
<style:font-face style:font-family-generic="system" style:font-pitch="variable" style:name="DejaVu Sans"
svg:font-family="'DejaVu Sans'"></style:font-face>
<style:font-face style:font-family-generic="system" style:font-pitch="variable" style:name="Lohit Hindi"
svg:font-family="'Lohit Hindi'"></style:font-face>
</office:font-face-decls>
<office:automatic-styles>
<style:style style:family="table-column" style:name="co1">
<style:table-column-properties fo:break-before="auto"
style:column-width="1.5866in"></style:table-column-properties>
</style:style>
<style:style style:family="table-column" style:name="co2">
<style:table-column-properties fo:break-before="auto"
style:column-width="1.222in"></style:table-column-properties>
</style:style>
<style:style style:family="table-column" style:name="co3">
<style:table-column-properties fo:break-before="auto"
style:column-width="0.889in"></style:table-column-properties>
</style:style>
<style:style style:family="table-row" style:name="ro1">
<style:table-row-properties fo:break-before="auto" style:row-height="0.1681in"
style:use-optimal-row-height="true"></style:table-row-properties>
</style:style>
<style:style style:family="table-row" style:name="ro2">
<style:table-row-properties fo:break-before="auto" style:row-height="0.1756in"
style:use-optimal-row-height="true"></style:table-row-properties>
</style:style>
<style:style style:family="table" style:master-page-name="Default" style:name="ta1">
<style:table-properties style:writing-mode="lr-tb" table:display="true"></style:table-properties>
</style:style>
<style:style style:family="table-cell" style:name="ce1" style:parent-style-name="Default">
<style:text-properties fo:font-weight="bold" style:font-weight-asian="bold"
style:font-weight-complex="bold"></style:text-properties>
</style:style>
</office:automatic-styles>
<office:body>
<office:spreadsheet>
<table:table table:name="Sheet1" table:style-name="ta1">
<office:forms form:apply-design-mode="false" form:automatic-focus="false"></office:forms>
<table:table-column table:default-cell-style-name="Default" table:style-name="co1"></table:table-column>
<table:table-column table:default-cell-style-name="Default" table:style-name="co2"></table:table-column>
<table:table-column table:default-cell-style-name="Default" table:style-name="co3"></table:table-column>
<table:table-row table:style-name="ro1">
<table:table-cell office:value-type="string" table:style-name="ce1">
<text:p>A</text:p>
</table:table-cell>
<table:table-cell office:value-type="string" table:style-name="ce1">
<text:p>B</text:p>
</table:table-cell>
<table:table-cell office:value-type="string" table:style-name="ce1">
<text:p>C</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="ro2">
<table:table-cell office:value-type="string">
<text:p>1</text:p>
</table:table-cell>
<table:table-cell office:value-type="string">
<text:p>2</text:p>
</table:table-cell>
<table:table-cell office:value-type="string">
<text:p>3</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:style-name="ro1">
<table:table-cell office:value-type="string">
<text:p>11</text:p>
</table:table-cell>
<table:table-cell office:value-type="string">
<text:p>22</text:p>
</table:table-cell>
<table:table-cell office:value-type="string">
<text:p>33</text:p>
</table:table-cell>
</table:table-row>
<table:table-row table:number-rows-repeated="1048572" table:style-name="ro1">
<table:table-cell table:number-columns-repeated="3"></table:table-cell>
</table:table-row>
<table:table-row table:style-name="ro1">
<table:table-cell table:number-columns-repeated="3"></table:table-cell>
</table:table-row>
</table:table>
<table:named-expressions></table:named-expressions>
</office:spreadsheet>
</office:body>
</office:document-content>
How can the XML be converted into a List (spreadsheet) of Lists (rows containing cell data) in Scala?
List(
List("A", "B", "C"),
List("1", "2", "3"),
List("11", "22", "33"),
)
You can use the backslash \ operator to go into the structure. Read the XPath bit of this Scala XML introduction.
val rowsXML = xml \ "body" \ "spreadsheet" \ "table" \ "table-row"
val rows = rowsXML.map(r => (r \ "table-cell" \ "p").map(_.text))
val rowsNE = rows.filterNot(_.forall(_.isEmpty))
The last line drops empty rows.