I am reading a xml file in groovy something like below, but don't know what is going wrong.
Below is my function
def setEnvironment(Map env,Map params)
{
def records=new XmlSlurper().parse(env.get("ABC_HOME")+"/isp/config/nodemeta.xml")
def jdbcurl=records.'domainservice:DBConnectivity'[0].#dbConnectString
params.put("dn", records.'domainservice:GatewayNodeConfig'[0].#domainName)
params.put("dh", records.'domainservice:GatewayNodeConfig'[0].'address'[0].#host)
params.put("dp", records.'domainservice:GatewayNodeConfig'[0].'address'[0].#httpPort)
params.put("u", records.'domainservice:DBConnectivity'[0].#dbUsername)
if(jdbcurl==null||jdbcurl.size()==0)
{
params.put("tns", records.'domainservice:DBConnectivity'[0].#dbHost)
}
else
{
params.put("tns", jdbcurl.find("(?<=%2F%2F)[\\d\\w_]+"))
}
println params
}
My Output
[pd:admin, u:, tns:, dh:, dn:, dp:, un:admin, x:c1164035531]
My Xml
<?xml version="1.0" encoding="UTF-8"?>
<imx:IMX xmlns:imx="http://com.abc.imx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" serializationSpecVersion="4.0" crcEnabled="0" xmlns:domainservice="http://com.abc.isp.metadata.domainservice/2" versiondomainservice="2.4.1" xmlns:common="http://com.abc.isp.metadata.common/2" versioncommon="2.2.0" xsi:schemaLocation="http://com.abc.imx IMX.xsd http://com.abc.isp.metadata.domainservice/2 com.abc.isp.metadata.domainservice.xsd http://com.abc.isp.metadata.common/2 com.abc.isp.metadata.common.xsd">
<domainservice:GatewayNodeConfig imx:id="U:LtWHxY0ZEeGb2FwhP-xoGw" adminconsolePort="15533" adminconsoleShutdownPort="38207" domainName="D_1035531" nodeName="N_1035531" dbConnectivity="ID_1">
<address imx:id="ID_2" xsi:type="common:NodeAddress" host="absdie" httpPort="1531" port="1532"/>
<portals>
<NodeRef imx:id="ID_3" xsi:type="common:NodeRef" address="ID_2" nodeName="N_1035531"/>
</portals>
</domainservice:GatewayNodeConfig>
<domainservice:DBConnectivity imx:id="ID_1" dbEncryptedPassword="ZmTXZDoYq0TyrU7fSaS9BrAlIuZyS2rw%2FafW1TLWE4g%3D" dbHost="fortuner" dbName="ORCL" dbPort="1521" dbType="ORACLE" dbUsername="zx1649355388"/>
</imx:IMX>
Note: pd & x are already there in the map
XmlSlurper is handling the namespaces for you... Just get rid of the namespace part of the node names (note the more Groovy map management as well)
params.dn = records.GatewayNodeConfig[0].#domainName.text()
params.dh = records.GatewayNodeConfig[0].address[0].#host.text()
params.dp = records.GatewayNodeConfig[0].address[0].#httpPort.text()
params.u = records.DBConnectivity[0].#dbUsername.text()
Related
I need some help/advice with JSON to XML conversion in Node js.
I have a service that gets a JSON object in request body that needs to convert to XML. I am able to achieve this using node-xml2js for json inputs with maximum one level of nested objects. But, it gets way more complicated with nested objects having attribute values. Attributes should be identified first, prefixed with $ sign and enclosed in curly braces before parsing through xml2js to get correct xml.
Is there a better way of doing this where this complicated layer of reformatting the json input can be simplified?
xml2js can converts this:
{
"Level1":{ "$":{ "attribute":"value" },
"Level2": {"$":{"attribute1":"05/29/2020",
"attribute2":"10","attribute3":"Pizza"}}
}
to this:(which is correct):
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Level1 attribute="value">
<Level2 attribute1="05/29/2020" attribute2="10" attribute3="Pizza"/>
</Level1>
But actual json input is this:
{
"Level1":{"attribute":"value",
"Level2": {"attribute1":"05/29/2020",
"attribute2":"10","attribute3":"Pizza"} }
}
Expected same result:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Level1 attribute="value">
<Level2 attribute1="05/29/2020" attribute2="10" attribute3="Pizza"/>
</Level1>
Please let me know if you have worked on similar requirements. Appreciate any help.
Thank you.
This would be a way to change the object back to the format expected in the library, although it assumes that all non object keys are supposed to be attributes (is that a valid assumption for your application?)
function groupChildren(obj) {
for(prop in obj) { // consider filtering for own properties (vs from prototype: for(prop of Object.keys(obj)) {
if (typeof obj[prop] === 'object') {
groupChildren(obj[prop]);
} else {
obj['$'] = obj['$'] || {};
obj['$'][prop] = obj[prop];
delete obj[prop];
}
}
return obj;
}
and then used like so:
var xml2js = require('xml2js');
var obj = {
Level1: {
attribute: 'value',
Level2: {
attribute1: '05/29/2020',
attribute2: '10',
attribute3: 'Pizza'
}
}
};
var builder = new xml2js.Builder();
var xml = builder.buildObject(groupChildren(obj));
which prints out:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Level1 attribute="value">
<Level2 attribute1="05/29/2020" attribute2="10" attribute3="Pizza"/>
</Level1>
you can use this library :nashwaan/xml-js
Like This:
let xmlJ=require('xml-js');
let parseToJson=(xml)=>{
return new Promise(resolve => {
let convert;
convert=xmlJ.xml2json(xml,{compact:true});
resolve(convert);
});
};
i have a xml from where i wish to remove few nodes. The idea i used is to run through all the root node children and keep writing to another file those nodes which i dont need to delete.
One problem I see is: the node attributes gets reordered in the written file which i dont want
my code looks like:
def xml = new XmlSlurper(false, false).parse(args[0])
ant.delete(file:fileName)
File f = new File(fileName)
xml.children().each{
String str = it.#name
if(some condiotion == false)
f << groovy.xml.XmlUtil.serialize(it)
}
another problem is that in the begining of every node it inserts
<?xml version="1.0" encoding="UTF-8"?>
There is no concrete example of the xml present in the question. Here is an example how a Node can be removed:
import groovy.xml.XmlUtil
def xml = '''
<School>
<Classes>
<Class>
<Teachers>
<Name>Rama</Name>
<Name>Indhu</Name>
</Teachers>
<Name>Anil</Name>
<RollNumber>16</RollNumber>
</Class>
<Class>
<Teachers>
<Name>Nisha</Name>
<Name>Ram</Name>
</Teachers>
<Name>manu</Name>
<RollNumber>21</RollNumber>
</Class>
</Classes>
</School>
'''
def parsed = new XmlSlurper().parseText( xml )
parsed.'**'.each {
if(it.name() == 'Teachers') {
it.replaceNode { }
}
}
XmlUtil.serialize( parsed )
In the above example, Teachers node is removed by doing a depthFirst search and iterating over each node and finally using replaceNode with an empty Closure. I hope this can be used as the logic you want.
PS: I have omitted the File operations for brevity.
The API work with a replacementStack. So, the replaceNode {} will show the result only when you serialize the node like:
GPathResult body = parsePath.Body
int oldSize = parsePath.children().size()
body.list()
body[0].replaceNode {} // Remove o no, mas não será visivel para o objeto pai, somente no momento de serializacao. Pois a API adiciona em uma pilha de alteracao que será usada na serializacao
String newXmlContent = XmlUtil.serialize(parsePath)
GPathResult newParsePath = new XmlSlurper().parseText(newXmlContent)
int newSize = newParsePath.children().size()
assertNotNull(this.parsePath)
assertEquals(2, oldSize)
assertEquals(1, newSize)
assertTrue(newSize < oldSize)
assertNotNull(body)
I have the following part of an XML file:
<properties>
<project.version>module.version</project.version>
<ie.version>17-8-103</ie.version>
<leg_uk.version>17-6-6</leg_uk.version>
<leg_na.version>17-8-103</leg_na.version>
</properties>
I want to generate a file with the following content:
ie.project.version = 17-8-103
leg_uk.project.version = 17-8-103
How to generate such file?
Is that what You're looking for?
def txt = """<properties>
<project.version>module.version</project.version>
<ie.version>17-8-103</ie.version>
<leg_uk.version>17-6-6</leg_uk.version>
<leg_na.version>17-8-103</leg_na.version>
</properties>"""
def xml = new XmlParser().parseText(txt)
new File('tmp').withWriter { w ->
xml.children().each {
w << "${it.name()}=${it.value().text()}\n"
}
}
i have the following xml to be parsed
<config>
<ParametricTesting>Y</ParametericTesting>
<FunctionalTesting>Y</FunctionalTesting>
<Utilities>N</Utilities>
<CommonApi>N</CommonApi>
<ClientData>N</ClientData>
<DataSourceTest>Y<DataSourceTest>
<Excel>
<ExcelFilePath>myexcel1.xlsx</ExcelFilePath>
</Excel>
<Access>
<AccessDB> </AccessDB>
</Access>
<Sql>
<SqlConnectionString> </SqlConnectionString>
</Sql>
<RunnerConsole>N</RunnerConsole>
<Schedular>N</Schedular>
</config>
I am using xmlreader to read the xml but since i am new to c# so i don't know why the code is breaking after reading second tag i.e ParametericTesting.
code:
string ConfigXml = Path.GetFullPath("Config.xml");
XmlReader xmlReader = XmlReader.Create(ConfigXml);
while (xmlReader.Read()) {
if ((xmlReader.NodeType== XmlNodeType.Element) && xmlReader.Name.Equals("ParametricTesting")) {
// TODO : write code relevant for parametric testing
xmlReader.Read();
}
else if ((xmlReader.NodeType== XmlNodeType.Element)&& xmlReader.Name.Equals("DataSourceTest")) {
string Datasource = xmlReader.GetAttribute("DataSourceTest");
if (Datasource.Equals("Y")) {
if (xmlReader.Name.Equals("Excel") && (xmlReader.NodeType == XmlNodeType.Element)) {
string excelfile = xmlReader.GetAttribute("ExcelFilePath");
string ExcelPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\Files\\" + excelfile;
objExcel.DataSourceName = excelfile;
objExcel.Open();
}
}
xmlReader.Read();
}
xmlReader.Read();
}
My code is not reading element beyond parametricTesting . Please help.
you open tag of "ParametricTesting" in the config.xml is different from the closing tag. correct it and that line passes.
also, you don't close the tag "DataSourceTest"
here is the fixed XML:
<config>
<ParametricTesting>Y</ParametricTesting>
<FunctionalTesting>Y</FunctionalTesting>
<Utilities>N</Utilities>
<CommonApi>N</CommonApi>
<ClientData>N</ClientData>
<DataSourceTest>Y</DataSourceTest>
<Excel>
<ExcelFilePath>myexcel1.xlsx</ExcelFilePath>
</Excel>
<Access>
<AccessDB> </AccessDB>
</Access>
<Sql>
<SqlConnectionString> </SqlConnectionString>
</Sql>
<RunnerConsole>N</RunnerConsole>
<Schedular>N</Schedular>
</config>
I want have the following output:
<?xml version="1.0" encoding="UTF-8"?>
<structure:structuralDataRoot xmlns:register="http://www.test.ch/register/1" xmlns:structure="http://test.ch/structure/1" >
<structure:tester>ZH</structure:tester>
<structure:surveyYear>2001</structure:surveyYear>
<structure:surfaceData>
<structure:houseSurfaceData>
<structure:creationDate>2001-01-01</structure:creationDate>
<structure:localFarmId>
<register:houseIdCategory>token</register:houseIdCategory>
<register:houseId>token</register:houseId>
</structure:localFarmId>
</structure:houseSurfaceData>
</structure>
I can add namespace to an xml like this:
xml.records('xmlns:structure' :"http://test.ch/structure/1" ...
But how I can make a namespace prefix to an xml-element?
The only solution I found was this:
tester('xmlns:structure' :"http://test.ch/structure/1", 'ZH')
But this gives me the follwing output:
<tester xmlns:structure='http://test.ch/structure/1'>ZH</tester>
It's syntactical correct, but not nice to read when you have many nodes.
You can do this (not sure it's what you want though)
import groovy.xml.StreamingMarkupBuilder
import groovy.xml.XmlUtil
def xmlBuilder = new StreamingMarkupBuilder()
writer = xmlBuilder.bind {
mkp.declareNamespace( register: "http://www.test.ch/register/1" )
mkp.declareNamespace( structure: "http://test.ch/structure/1" )
'structure:structuralDataRoot' {
'structure:tester'( 'ZH' )
'structure:surveyYear'( 2001 )
'structure:surfaceData' {
'structure:houseSurfaceData' {
'structure:creationDate'( '2001-01-01' )
'structure:localFarmId' {
'register:houseIdCategory'( 'token' )
'register:houseId'( 'token' )
}
}
}
}
}
println XmlUtil.serialize( writer )
That code outputs:
<?xml version="1.0" encoding="UTF-8"?>
<structure:structuralDataRoot xmlns:register="http://www.test.ch/register/1" xmlns:structure="http://test.ch/structure/1">
<structure:tester>ZH</structure:tester>
<structure:surveyYear>2001</structure:surveyYear>
<structure:surfaceData>
<structure:houseSurfaceData>
<structure:creationDate>2001-01-01</structure:creationDate>
<structure:localFarmId>
<register:houseIdCategory>token</register:houseIdCategory>
<register:houseId>token</register:houseId>
</structure:localFarmId>
</structure:houseSurfaceData>
</structure:surfaceData>
</structure:structuralDataRoot>