Remove XML content retaining a given Node (Java parser) - java

In the XML example below, using a java parser how to keep the content under the tag AND followed by center and remove everything else?
The tag might have other instances when is followed by other tags than center, and those has to be discarded.
<xml>
<A>
<B>
.
.
.
<parameter>
<parameterid>center</parameterid>
<name>Center</name>
<keyframe>
<when>1</when>
<value>
<horiz>100</horiz>
<vert>100</vert>
</value>
</keyframe>
<keyframe>
<when>2</when>
<value>
<horiz>150</horiz>
<vert>150</vert>
</value>
</keyframe>
</parameter>
<parameter>
...
</parameter>
<parameter>
...
</parameter>
.
.
.
</B>
</A>
</xml>
So the output will look like:
<parameter>
<parameterid>center</parameterid>
<name>Center</name>
<keyframe>
<when>1</when>
<value>
<horiz>100</horiz>
<vert>100</vert>
</value>
</keyframe>
<keyframe>
<when>2</when>
<value>
<horiz>150</horiz>
<vert>150</vert>
</value>
</keyframe>
</parameter>
Please advise. Thanks!

You can use Java Regexp to remove unneeded content, and then parse only needed part f.e.
String sourceXML = readFileToString("source.xml")
final Pattern pattern = Pattern.compile(".*(<parameter>.+</parameter>).*",Pattern.DOTALL);
Matcher matcher = pattern.matcher(sourceXML);
if (matcher.find()) {
String xmlToParse = matcher.group(0);
someDomOrSaxParser.parseFromString(xmlToParse)
}else
System.out.println("NO MATCH");

This would be a good job for an XSLT stylesheet.
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:apply-templates select="node()|#*"/>
</xsl:template>
<xsl:template match="parameter[parameterid='center']">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
applied to the input in the question, produces the following output:
<parameter>
<parameterid>center</parameterid>
<name>Center</name>
<keyframe>
<when>1</when>
<value>
<horiz>100</horiz>
<vert>100</vert>
</value>
</keyframe>
<keyframe>
<when>2</when>
<value>
<horiz>150</horiz>
<vert>150</vert>
</value>
</keyframe>
</parameter>
If you have any questions on using XSLT in Java, please take a look at this question.

Related

XSLT 3.0 Identity transform document collection?

I have one XSLT 3.0:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:n1="urn:hl7-org:v3">
<xsl:output indent="yes" method="xml" encoding="utf-8"/>
<xsl:param name="icd10Map" as="map(xs:string, xs:string)"
select="
map {
'1742': 'C502',
'55090': 'K409',
'8442': 'S8350',
'7172': 'M2332',
'36616': 'H251',
'4550': 'K648'
}"/>
<xsl:variable name="map-keys" select="map:keys($icd10Map)"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="n1:translation[#codeSystemName = 'ICD-9-CM']/#code">
<xsl:attribute name="code">
<xsl:value-of select="$icd10Map($map-keys[translate(normalize-space(current()), '
.;', '') = .])"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
One input XML:
<?xml-stylesheet type="text/xsl" href="./Content/xsl/CDA.xsl"?>
<ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:hl7-org:v3 NIST_C32_schema/C32_CDA.xsd" xmlns="urn:hl7-org:v3" xmlns:sdtc="urn:hl7-org:sdtc">
<realmCode code="US" />
<typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040" />
<templateId root="2.16.840.1.113883.10.20.22.1.1" />
************************************************************
<id extension="TT988" root="2.16.840.1.113883.19.5.99999.1" />
<code codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" code="11504-8" displayName="Surgical Operation Note" />
<title>Operative Report</title>
****************************************************
<component>
<structuredBody>
<component>
<section>
***********************
<entry>
<act moodCode="EVN" classCode="ACT">
<templateId root="2.16.840.1.113883.10.20.22.4.65" />
<code code="10219-4" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Preoperative Diagnosis" />
<entryRelationship typeCode="SUBJ">
<observation classCode="OBS" moodCode="EVN">
<code code="282291009" displayName="Diagnosis" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" />
<statusCode code="completed" />
<!-- ICD-9 be transformed to ICD-10 -->
<value nullFlavor="OTH" type="CD">
<translation code="366.16" displayName="Nuclear sclerosis" codeSystem="2.16.840.1.113883.6.103" codeSystemName="ICD-9-CM" />
</value>
</observation>
</entryRelationship>
</act>
</entry>
</section>
</component>
</structuredBody>
</component>
</ClinicalDocument>
The transformation scenario in Oxygen with just one document is without issue:
*******************
<value nullFlavor="OTH" type="CD">
<translation code="H251"
displayName="Nuclear sclerosis"
codeSystem="2.16.840.1.113883.6.103"
codeSystemName="ICD-9-CM"/>
</value>
******************
However, XSLT 3.0 identity transform for collection seems working like this:
<xsl:variable name="inFile" as="node()*" select="collection('hl7.xml')"/>
<xsl:template match="/">
<xsl:text>
ICD9 Target Transformation in the collection is:
</xsl:text>
<xsl:for-each select="$inFile//n1:translation[#codeSystemName = 'ICD-9-CM']/#code">
<xsl:value-of select="$icd10Map($map-keys[translate(normalize-space(current()), '
.;', '') = .])" separator=" , "/>
</xsl:for-each>
</xsl:template>
Result:
ICD9 Target Transformation in the collection is:
H251
H251
K648
K648
K409
K409
S8350
M2332
M2332
S8350
If I change the XSLT to:
<xsl:mode on-no-match="shallow-copy"/>
<xsl:variable name="inFile" as="node()*" select="collection('hl7.xml')"/>
<xsl:template match="n1:translation[#codeSystemName = 'ICD-9-CM']/#code">
<xsl:text>
ICD9 Target Transformation in the collection is:
</xsl:text>
<xsl:for-each select="$inFile">
<xsl:attribute name="code">
<xsl:value-of select="$icd10Map($map-keys[translate(normalize-space(current()), '
.;', '') = .])" separator=" , "/>
</xsl:attribute>
</xsl:for-each>
</xsl:template>
It doesn’t appear any transform happen and is merely an extraction of the URI list in the catalog file hl7.xml.
I develop a Java application which can bulk validate documents against XSD, transform (without collection()) and finally write the documents into database. The logging is the desired result:
Engine Instantiation: com.fc.andante.sax.SAXValidateStreamTransformWrite
Schema Validation Status: files in:/ml/Andante/data/data are validated against schema file:/ml/Andante/data/operation-transform.xsd
User 'auditor' has validated files in:/ml/Andante/data/data on 2020-08-26T23:05:26.357431
*****************
Transaction Status: Authenticating database writer...
Transaction Status: User audited as 'super' is transforming document set...
Transaction Status: Document data/data/cataract.xml is successfully transformed and written into database with uri '/xslt-transform/cataract.xml'
Transaction Status: Document data/data/breast-surgery.xml is successfully transformed and written into database with uri '/xslt-transform/breast-surgery.xml'
Transaction Status: Document data/data/hernia.xml is successfully transformed and written into database with uri '/xslt-transform/hernia.xml'
Transaction Status: Document data/data/colonoscopy.xml is successfully transformed and written into database with uri '/xslt-transform/colonoscopy.xml'
Transaction Status: Document data/data/knee.xml is successfully transformed and written into database with uri '/xslt-transform/knee.xml'
Die Transaktion wurde erfolgreich abgeschlossen 2020-08-26T23:05:28.341385700
Can anyone help to solve the XSLT 3.0 Collections transform issue?
I would use a global parameter
<xsl:param name="inFiles" as="document-node()*" select="collection('hl7.xml')"/>
and then start processing with a named template
<xsl:template name="xsl:initial-template">
<xsl:for-each select="$inFiles">
<xsl:result-document href="/xslt-transform/{tokenize(document-uri(), '/')[last()]}">
<xsl:apply-templates/>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
Then you can xsl:import your first XSLT sample from the question or of course edit it to insert the code I have shown. Make sure you let Saxon start with the named template (-it command line option for Saxon; in oXygen by not providing a source document).

Unable to fetch the specific entire XML tag by using XSLT

I have the below sample XML file
Sample XML:
<?xml version="1.0" encoding="UTF-8"?>
<testng-results skipped="0" failed="0" total="10" passed="10">
<class name="com.transfermoney.Transfer">
<test-method status="PASS" name="setParameter" is-config="true" duration-ms="4"
started-at="2018-08-16T21:43:38Z" finished-at="2018-08-16T21:43:38Z">
<params>
<param index="0">
<value>
<![CDATA[org.testng.TestRunner#31c2affc]]>
</value>
</param>
</params>
<reporter-output>
</reporter-output>
</test-method> <!-- setParameter -->
</class>
<class name="com.transfermoney.Transfer">
<test-method status="FAIL" name="setSettlementFlag" is-config="true" duration-ms="5"
started-at="2018-08-16T21:44:55Z" finished-at="2018-08-16T21:44:55Z">
<reporter-output>
<line>
<![CDATA[runSettlement Value Set :false]]>
</line>
</reporter-output>
</test-method> setSettlementFlag
</class>
</testng-results>
I just want to take the below piece of tags from above XML file based on status PASS (I don't want to take <?XML version, <testng-results> and class tags those are should be ignored).
Expected Output:
<test-method status="PASS" name="setParameter" is-config="true" duration-ms="4"
started-at="2018-08-16T21:43:38Z" finished-at="2018-08-16T21:43:38Z">
<params>
<param index="0">
<value>
<![CDATA[org.testng.TestRunner#31c2affc]]>
</value>
</param>
</params>
<reporter-output>
</reporter-output>
</test-method>
I just used below XSLT to get the above output from sample XML file but It doesn't work It returned all the tags but I just want the above output not other than anything.
XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>"
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="class"/>
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
<xsl:for-each select="test-method[#status='PASS']">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:stylesheet>
Also Using the below java code to run the XSLT and sample XML file
Code:
String XML = fetchDataFrmXML(".//Test//testng-results_2.xml");
Transformer t = TransformerFactory.newInstance().newTransformer(new StreamSource(new StringReader(XSL)));
t.transform(new StreamSource(new StringReader(XML)), new StreamResult(new File(".//Test//Sample1.xml")));
This is the sample payload. But the actual payload had multiple nodes with "PASS" and "Failed" status. I'm just only interested to fetch the PASS node in the above output format.
Any leads....
The result you show could be obtained quite simply by doing just:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/testng-results">
<xsl:copy-of select="class/test-method[#status='PASS']" />
</xsl:template>
</xsl:stylesheet>
However, in case of more than one test-method having a status of "PASS" this will result in an XML fragment with no single root element. So you'd probably be better off doing:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/testng-results">
<root>
<xsl:copy-of select="class/test-method[#status='PASS']" />
</root>
</xsl:template>
</xsl:stylesheet>

how to generate an xml with name value pair from key value paired xml?

i have an XML generated in the below form from JSON to XML Conversion.
<entry>
<string>dataset_code</string>
<string>GDP</string>
</entry>
How to convert this into the below format in XML?
<entry>
<dataset_code>GDP</dataset_code>
</entry>
Note: Here the key-value pairs(dataset_code, GDP, entry) are dynamic.
Any help on this would be highly appreciated!
In XSLT, this would be done as:
<xsl:template match="/*">
<xsl:copy>
<xsl:element name="{string[1]}">
<xsl:value-of select="string[2]" />
</xsl:element>
</xsl:copy>
</xsl:template>
Note that this can easily fail if the first string is not a valid XML element name.
I'm not an expert but playing with http://www.freeformatter.com/xsl-transformer.html I've found this solution:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<entry>
<xsl:text disable-output-escaping="yes"><</xsl:text><xsl:value-of select="(entry/string)[1]"/><xsl:text disable-output-escaping="yes">></xsl:text>
<xsl:value-of select="(entry/string)[2]"/>
<xsl:text disable-output-escaping="yes"><</xsl:text>/<xsl:value-of select="(entry/string)[1]"/><xsl:text disable-output-escaping="yes">></xsl:text>
</entry>
</xsl:template>
</xsl:stylesheet>
Hope it helps

Using java list filled with database values to iterate over xsl transformation and produce multiple xml

I am using custom xpath function call in xslt, where my method is returning a list of objects fetched from database. I have to generate multiple xml based on the number of resultset i am getting from database.
Which is resulting in exception:
Error on line 28 of comptel.xsl:
XPTY0020: Required item type of the context item for the child axis is node(); actual type
is xs:string
in built-in template rule
Exception during transformation
; SystemID: file:/F:/OMFOLDER/comptel.xsl; Line#: 28; Column#: -1
net.sf.saxon.trans.XPathException: Required item type of the context item for the child axis is node(); actual type is xs:string
at com.saxonica.ee.bytecode.util.Callback.makeXPathException(Callback.java:143)
at EE_OrderSubline_5215127407.process(file:/F:/OMFOLDER/comptel.xsl:79)
at com.saxonica.ee.bytecode.CompiledExpression.process(CompiledExpression.java:69)
at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(TemplateRule.java:395)
at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:456)
at net.sf.saxon.trans.TextOnlyCopyRuleSet.process(TextOnlyCopyRuleSet.java:65)
at net.sf.saxon.trans.Mode.applyTemplates(Mode.java:433)
at net.sf.saxon.Controller.transformDocument(Controller.java:2261)
at net.sf.saxon.Controller.transform(Controller.java:1863)
at net.sf.saxon.s9api.XsltTransformer.transform(XsltTransformer.java:553)
at net.sf.saxon.jaxp.TransformerImpl.transform(TransformerImpl.java:183)
at com.thbs.provision.XSLTSaxonica.transformSaxonmain(XSLTSaxonica.java:212)
at com.thbs.provision.JPAServlet.service(JPAServlet.java:43)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:280)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:254)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:136)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:341)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:238)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3363)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3333)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2220)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2146)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2124)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1564)
at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:295)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:254)
Here is my Java class
public static List<String> assignDbvalue()
{
try {
conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs=null;
rs = ps.executeQuery();
ResultSetMetaData metadata = rs.getMetaData();
int numberOfColumns = metadata.getColumnCount();
System.out.println("numberOfColumns "+numberOfColumns);
for(int i=1;i<=numberOfColumns;i++)
{
while (rs.next()) {
arrayList.add(rs.getString(i));
System.out.println(rs.getString(i));
}
}
return arrayList;
}
And here is my xslt:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sql="http://ns.saxonica.com/sql"
xmlns:nd="java:com.thbs.provision.XSLTSaxonica"
xmlns:exslt="http://exslt.org/common"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:java="http://saxon.sf.net/java-type"
xmlns:saxon="http://saxon.sf.net/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
exclude-result-prefixes="java saxon xsd xsi xsl sql"
extension-element-prefixes="saxon sql"
>
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"
/>
<xsl:template match="OrderSubline">
<xsl:for-each select="exslt:node-set(nd:assignDbvalue())">
<ModifyRequest xmlns="http://soa.comptel.com/2011/02/instantlink">
<RequestHeader>
<NeType>BST</NeType>
<OrderNo><xsl:value-of select="OrderNumber/text()"/></OrderNo>
<ReqUser><xsl:value-of select="Source/text()"/></ReqUser>
</RequestHeader>
<RequestParameters>
<Parameter>
<xsl:attribute name="name">REQ_OBJ</xsl:attribute>
<xsl:attribute name="value">1</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">REQ_TYPE</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="OrderSublineType/text()"/>
</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">IL_REQ_GROUP</xsl:attribute>
<xsl:attribute name="value">BHARTI</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">ACT_CODE1</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">RESP_QUEUE_ID</xsl:attribute>
<xsl:attribute name="value">SYNCSOA</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">MSISDN</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="MobileNumber/text()"/>
</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">CIRCLE_ID</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="Circle/text()"/>
</xsl:attribute>
</Parameter>
<Parameter>
<xsl:attribute name="name">PROD_ID_1</xsl:attribute>
<xsl:attribute name="value">
<xsl:value-of select="ProductItem/ProductItemId/text()"/>
</xsl:attribute>
</Parameter>
</RequestParameters>
</ModifyRequest>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Kindly suggest if i am missing something or is there any other way to achieve it.
Your extension function is returning a List, and you're then applying exsl:node-set() to it. Perhaps you are assuming that this will turn the strings into nodes? In Saxon, exsl:node-set() is an identity function - it returns its argument unchanged. So you are iterating over a sequence of strings using xsl:for-each, and then with the context item as a string you are using expressions like select="OrderNumber/text() which don't work unless the context item is a node.
If the strings returned by your extension function are fragments of lexical XML, then use the parse-xml() function to turn them into nodes, not exsl:node-set().
(Note: I think there are some implementations of exsl:node-set() where, if you supply a string, they will parse the string as lexical XML. However, there's nothing in the spec at http://www.exslt.org/ to encourage this interpretation.)

xsl to search for all occurences of part of the text in xml, comparing from the passed list of texts and replacing it by a node

The input file is as below:
<root>
<node1>
<child_node1>apple mango<sub_node1>water grapes</sub_node1> banana</child_node1>
<child_node2>Cherry mango<sub_node2>Date grapes</sub_node2> Coconut</child_node2>
</node1>
<node2>
<child_node3>banana grapes apple</child_node3>
</node2>
......
</root>
An XSL is required which works for the below requirement.
Requirement:
Need to pass the list of strings and each string from that list has to be checked in this input file for all occurrences of matching text. If found enclose that matched text with a tag say <fruit>.
Example:
For the above input file if I pass list of Strings including: grapes, apple
The Expected output:
<root>
<node1>
<child_node1><fruit>apple</fruit> mango<sub_node1>water <fruit>grapes</fruit></sub_node1> banana</child_node1>
<child_node2>Cherry mango<sub_node2>Date <fruit>grapes</fruit></sub_node2> Coconut</child_node2>
</node1>
<node2>
<child_node3>banana <fruit>grapes</fruit> <fruit>apple</fruit></child_node3>
</node2>
......
</root>
Only the exact matching text needs to be tagged and "<child_node1>apple mango<sub_node1>water grapes</sub_node1> banana</child_node1>" is still valid (The Nodes and its text).
The list of input Strings may be any thing and a generic string matching approach is required which checks with each string in that list.
Any help in this regard is greatly appreciated. Thanks a lot in advance!
i tried something that goes like this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" method="xml" />
<xsl:strip-space elements="*" />
<xsl:variable name="list">apple mango</xsl:variable>
<xsl:template match="node() | #*">
<xsl:copy>
<xsl:apply-templates select="node() | #*" />
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:for-each select="tokenize(., '\s+')">
<xsl:choose>
<xsl:when test=". = tokenize($list, '\s+')">
<fruit><xsl:value-of select="."/></fruit>
</xsl:when>
<xsl:otherwise><xsl:copy-of select="."/></xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Categories

Resources