Delete line from xml based on condition - java

I have an xml as shown below.
<?xml version="1.0" encoding="utf-8"?>
<package date-created="11/4/2014" client-version="blah" system-version="blah">
<description />
<system>
<language />
</system>
<res id="blah" name="name" path="path" type="F" mimeType="mimetype-blah">
<description />
<keywords />
<resver id="1690047800" major="50" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
<resver id="1690167421" major="68" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
<resver id="1690176842" major="71" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
<res id="blah1" name="name1" path="path1" type="F" mimeType="mimetype-blah1">
<description />
<keywords />
<resver id="1690145841" major="34" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
<resver id="1690161885" major="64" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
<resver id="1690165275" major="66" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
<resver id="1690169108" major="69" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
<resver id="1690175442" major="87" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
</package>
I want to delete all <resver> elements except for the one with highest "major" attribute value.
For example above major="71" is highest in the first resver group and major="87" is the highest in second resver group.
So overall output looks like this:
<?xml version="1.0" encoding="utf-8"?>
<package date-created="11/4/2014" client-version="blah" system-version="blah">
<description />
<system>
<language />
</system>
<res id="blah" name="name" path="path" type="F" mimeType="mimetype-blah">
<description />
<keywords />
<resver id="1690176842" major="71" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
<res id="blah1" name="name1" path="path1" type="F" mimeType="mimetype-blah1">
<description />
<keywords />
<resver id="1690175442" major="87" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" workflow-step="1000" />
</res>
</package>
I thought of using JAXB to do the work. Is there a better way to solve this?
Can this be done with Simple Java File api?
Answer
I have written this thing using JAXB to acheive this.
Here is the code
try {
File file = new File(FILE);
JAXBContext jaxbContext = JAXBContext.newInstance(Package.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Package pack = (Package) jaxbUnmarshaller.unmarshal(file);
if (pack.getRes() == null || pack.getRes().size() == 0) {
System.out.println("Size zero - exit");
return;
}
for (Package.Res res : pack.getRes()) {
if (! (res.getResver().size() == 1)) {
Short max = getMaxMajorVersion(res);
List<Package.Res.Resver> resverList = removeNonMaxResver(res, max);
for (Package.Res.Resver resver : resverList)
res.getResver().remove(resver);
}
}
finalPack = pack;
} catch (JAXBException e) {
e.printStackTrace();
}
marshal();
Method: extractNonMaxResver
private static List<Package.Res.Resver> removeNonMaxResver(
Package.Res res, Short max) {
List<Package.Res.Resver> resverList = new ArrayList<Package.Res.Resver>();
for (Package.Res.Resver resver : res.getResver()) {
if (resver.getMajor() != max)
resverList.add(resver);
}
return resverList;
}
Method: getMaxMajorVersion
private static Short getMaxMajorVersion(Package.Res res) {
List<Short> list = new ArrayList<Short>();
for (Package.Res.Resver resver : res.getResver()) {
list.add(resver.getMajor());
}
Short max = Collections.max(list);
System.out.println("Max: " + max);
return max;
}
Method: marshal
public static void marshal() {
try {
File file = new File(FILE_OUT);
JAXBContext jaxbContext = JAXBContext.newInstance(Package.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
Boolean.TRUE);
jaxbMarshaller.marshal(finalPack, file);
jaxbMarshaller.marshal(finalPack, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}

You need to load the XML into either XMLElement or a Java object(using JAXB or other lib). If using XMLEement then you will be iterating through nodes and deleting as per your condition. and in case of Java Model object, just iterate through the list delete them and then persist the same Model as XML file.
Go through the Java Docs :https://docs.oracle.com/javase/7/docs/api/org/w3c/dom/Element.html
It has all API which you can use to manipulate XML.

XML is not a programming language.
you cant add conditions on it, but the same is possible with processing languages such as XSLT.
<xsl:if test="#foo='bar'">
<xsl:text>Hello, world!</xsl:text>
</xsl:if>
I suggest that as the best way to do this kind of operations.
Other possible operations are by parsing the XML String using basic String operations. Its complex and confusing and more error prone.
Ref This

Related

Getting a specific child node from XML JAVA

<DistinctParty FixedRef="10569">
<Comment />
<Profile ID="10569" PartySubTypeID="4">
<Identity ID="952" FixedRef="10569" Primary="true" False="false">
<Alias FixedRef="10569" AliasTypeID="1403" Primary="true" LowQuality="false">
<DocumentedName ID="952" FixedRef="10569" DocNameStatusID="1">
<DocumentedNamePart>
<NamePartValue NamePartGroupID="36916" ScriptID="215" ScriptStatusID="1" Acronym="false">MAKHLUF</NamePartValue>
</DocumentedNamePart>
<DocumentedNamePart>
<NamePartValue NamePartGroupID="36917" ScriptID="215" ScriptStatusID="1" Acronym="false">Hafiz</NamePartValue>
</DocumentedNamePart>
</DocumentedName>
</Alias>
<Alias FixedRef="10569" AliasTypeID="1400" Primary="false" LowQuality="false">
<DocumentedName ID="12197" FixedRef="10569" DocNameStatusID="2">
<DocumentedNamePart>
<NamePartValue NamePartGroupID="18042" ScriptID="215" ScriptStatusID="1" Acronym="false">MAKHLOUF</NamePartValue>
</DocumentedNamePart>
<DocumentedNamePart>
<NamePartValue NamePartGroupID="18043" ScriptID="215" ScriptStatusID="1" Acronym="false">Hafez</NamePartValue>
</DocumentedNamePart>
</DocumentedName>
</Alias>
<NamePartGroups>
<MasterNamePartGroup>
<NamePartGroup ID="36916" NamePartTypeID="1520" />
</MasterNamePartGroup>
<MasterNamePartGroup>
<NamePartGroup ID="36917" NamePartTypeID="1521" />
</MasterNamePartGroup>
<MasterNamePartGroup>
<NamePartGroup ID="18042" NamePartTypeID="1520" />
</MasterNamePartGroup>
<MasterNamePartGroup>
<NamePartGroup ID="18043" NamePartTypeID="1521" />
</MasterNamePartGroup>
</NamePartGroups>
</Identity>
<Feature ID="5887" FeatureTypeID="8">
<FeatureVersion ID="570" ReliabilityID="1">
<Comment />
<DatePeriod CalendarTypeID="1" YearFixed="false" MonthFixed="false" DayFixed="false">
<Start Approximate="true" YearFixed="false" MonthFixed="false" DayFixed="false">
<From>
<Year>1975</Year>
<Month>1</Month>
<Day>1</Day>
</From>
<To>
<Year>1975</Year>
<Month>1</Month>
<Day>1</Day>
</To>
</Start>
<End Approximate="true" YearFixed="false" MonthFixed="false" DayFixed="false">
<From>
<Year>1975</Year>
<Month>12</Month>
<Day>31</Day>
</From>
<To>
<Year>1975</Year>
<Month>12</Month>
<Day>31</Day>
</To>
</End>
</DatePeriod>
<VersionDetail DetailTypeID="1430" />
</FeatureVersion>
<IdentityReference IdentityID="952" IdentityFeatureLinkTypeID="1" />
</Feature>
<Feature ID="5888" FeatureTypeID="9">
<FeatureVersion ID="571" ReliabilityID="1">
<Comment />
<VersionDetail DetailTypeID="1432">Damascus, Syria</VersionDetail>
</FeatureVersion>
<IdentityReference IdentityID="952" IdentityFeatureLinkTypeID="1" />
</Feature>
<Feature ID="164625" FeatureTypeID="25">
<FeatureVersion ID="214625" ReliabilityID="1">
<Comment />
<VersionLocation LocationID="14625" />
</FeatureVersion>
<IdentityReference IdentityID="952" IdentityFeatureLinkTypeID="1" />
</Feature>
<Feature ID="310569" FeatureTypeID="26">
<FeatureVersion ID="410569" ReliabilityID="1">
<Comment />
<VersionDetail DetailTypeID="1432">Colonel</VersionDetail>
</FeatureVersion>
<IdentityReference IdentityID="952" IdentityFeatureLinkTypeID="1" />
</Feature>
</Profile>
</DistinctParty>
This is an XML and its root is DistinctParty, now I need to extract two tags from it via JAVA.
NamePartyValue
VersionDetail
Now I get the root element and can extract NamePartyValue with these methods, but I also need to extract VersionDetail element which I can't even find in the result, could you please direct me in an accurate direction.
public NodeList readXMLFileUpdated(String path) {
File fXmlFile = new File(path);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
Document doc = null;
NodeList nList = null;
try {
dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
nList = doc.getElementsByTagName("DistinctParty");
} catch (Exception e) {
e.printStackTrace();
}
return nList;
}
public List<Company> getCompanyNamesXML(NodeList nodes){
List<Company> listOfCompanies = new ArrayList<>();
for(int i = 0; i<nodes.getLength(); i++)
listOfCompanies.add(new Company(nodes.item(i).getTextContent()));
return listOfCompanies;
}
This statement nodes.item(i).getTextContent() in upper method returns me the value of NamePartyValue field and when trying to get children of this node with this nodes.item(i).getChildNodes() I can't see VersionDetail in the result, any idea what I might be missing?
Just like you found the NodeList of "DistincyParty" by calling doc.getElementsByTagName(), you can find VersionDetail or NamePartValue elements by doing the same thing.

jaxb null values while unmarshalling

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xml>
<Settings version="3" xmlns="urn:Adapter-v3">
<Connections>
<Connection name ="A" description="DEV">
<SaveVersion version="M" siteURL="https://example.com" />
<Save>
<Id>id123</Id>
<Client>hello</Client>
</Save>
</Connection>
<Connection name ="B" description="DEV1">
<SaveVersion version="M" siteURL="https://example.com" />
<Auth>
<UserId>id123</UserId>
<Password>pass</Password>
</Auth>
</Connection>
</Connections>
<Mappings>
<Mapping cont="AA" auction="A1">
<Description>Desc</Description>
<Content
attr1="IO"
attr2="d"
attr3="Information"
attr4="false"
<Element enabled="false" count="200" prefix="DocLib_" itemPrefix="0" />
<Sub enabled="false" count="100" prefix="Folder_" itemPrefix="0" />
<FilenameA auction="N" delay="3" />
</Content>
</Mapping>
<Mapping cont="AB" auction="SharePointOLDev1">
<Description>Desc</Description>
<Content
attr1="IO"
attr2="d"
attr3="Information"
attr4="false"
<Element enabled="false" count="200" prefix="DocLib_" itemPrefix="0" />
<Sub enabled="false" count="100" prefix="1" itemPrefix="0" />
</Content>
</Mapping>
</Mappings>
<TypeMappings>
<TypeMapping Type="rfid" ext="msg" />
</TypeMappings>
</Settings>
Trying to unmarshal the above xml file to java objects.
Generated Settings.java and ObjectFactory.java file using xjc tool.These files are deployed in the src folder(along with other java files.)
WHen i unmarshal i get null valuues for Connections,Mappings and TypeMappings.
Is there any steps that i am missing?
public class JAXBImpl{
public static void main(String args[]){
JAXBContext jaxbContext;
Settings que= null;
jaxbContext = JAXBContext.newInstance(Settings.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
que= (Settings) jaxbUnmarshaller.unmarshal(file);
System.out.println(que.getConnections().getConnection());
}
}

jBPM compilation error

Process Compilation error : org.drools.lang.descr.ProcessDescr#4c60d6e9
com/sample/Process_com_sample_ruleflowsample.java (21:862) : Type mismatch: cannot convert from int to String
com/sample/Process_com_sample_ruleflowsample.java (29:1151) : Type mismatch: cannot convert from int to String
This is my ruleflowsample.rf under src/main/rules that is throwing the above error.
<?xml version="1.0" encoding="UTF-8"?>
<process xmlns="http://drools.org/drools-5.0/process"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xs:schemaLocation="http://drools.org/drools-5.0/process drools-processes-5.0.xsd"
type="RuleFlow" name="ruleflowsample" id="com.sample.ruleflowsample" package-name="com.sample" >
<header>
<imports>
<import name="com.sample.Employee" />
</imports>
<variables>
<variable name="caffeineIntake" >
<type name="org.drools.process.core.datatype.impl.type.FloatDataType" />
</variable>
</variables>
</header>
<nodes>
<start id="1" name="Start" x="12" y="129" width="48" height="48" />
<split id="2" name="Gateway" x="101" y="128" width="49" height="49" type="2" >
<constraints>
<constraint toNodeId="4" toType="DROOLS_DEFAULT" name="Coffee" priority="1" type="code" dialect="java" >return caffeineIntake>0.105F;</constraint>
<constraint toNodeId="5" toType="DROOLS_DEFAULT" name="Tea" priority="1" type="code" dialect="java" >return caffeineIntake>0.04F;</constraint>
</constraints>
</split>
<actionNode id="4" name="Coffee" x="198" y="205" width="80" height="48" >
<action type="expression" dialect="java" >String noOfCups = 1;
System.out.println("No of coffee cups = "+noOfCups);
System.out.println("caffeineIntake");</action>
</actionNode>
<actionNode id="5" name="Tea" x="196" y="61" width="80" height="48" >
<action type="expression" dialect="java" >String noOfCups = 1;
System.out.println("No of tea cups = "+noOfCups);
System.out.println("caffeineIntake");</action>
</actionNode>
<end id="6" name="End" x="386" y="127" width="48" height="48" />
<join id="7" name="Gateway" x="311" y="127" width="49" height="49" type="2" />
</nodes>
<connections>
<connection from="1" to="2" />
<connection from="2" to="4" />
<connection from="2" to="5" />
<connection from="7" to="6" />
<connection from="5" to="7" />
<connection from="4" to="7" />
</connections>
</process>
I know the error is occurring because of this line: System.out.println("caffeineIntake");
I want to access this input variable i.e. caffeineIntake to perform some operation on it.
The error is not occurring because of this line: System.out.println("caffeineIntake");
It is occurring because of the Dialect option selection:
Using this option as mvel rather than java resolved the issue.
Well,
from my point of view
String noOfCups = 1;
is the problem.
perhaps change it to
String noOfCups = "1";

How to change output coding of a XML of reading and writing at the same time in with Jdom?

I have this code, I want to read and want to write the "prueba3.xml" at the same time, the file is UTF8 but when I write the file, the encoding changes and displays strange characters, although I have added format.setEncoding("UTF-8"), it is not doing it correctly. Is it possible to change the output encoding to UTF8 with jdom SAXBuilder?
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<prueba>
<reg id="576340">
<dato cant="856" id="6" val="-1" num="" desc="ñápás" />
<dato cant="680" id="1" val="-1" num="" desc="résd" />
<dato cant="684" id="5" val="-1" num="" desc="..да и вообем" />
<dato cant="1621" id="1" val="-1" num="" desc="hi" />
<dato cant="1625" id="5" val="-1" num="" desc="Hola" />
</reg>
</prueba>
This is the code:
public static void main(String[] args) throws FileNotFoundException, JDOMException, IOException
{
//Se crea un SAXBuilder para poder parsear el archivo
File xml = new File("c:\\prueba3.xml");
Document doc = (Document) new SAXBuilder().build(xml);
Element raiz = doc.getRootElement();
//Recorremos los hijos de la etiqueta raíz
List articleRow = raiz.getChildren("reg");
for (int i = 0; i < articleRow.size(); i++) {
Element row = (Element) articleRow.get(i);
List images = row.getChildren("dato");
for (int j = 0; j < images.size(); j++) {
Element row2 = (Element) images.get(j);
String texto = row2.getAttributeValue("desc") ;
String id = row2.getAttributeValue("id");
if ((texto != null) && (texto !="") && (id.equals("1"))){
row2.getAttribute("desc").setValue("Raúl").toString();
}
}
Format format = Format.getRawFormat();
format.setEncoding("UTF-8");
XMLOutputter xmlOutput = new XMLOutputter(format);
xmlOutput = new XMLOutputter(format);
xmlOutput.output(doc, new FileWriter("c:\\prueba3.xml"));
}
System.out.println("fin");
}
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<prueba>
<reg id="576340">
<dato cant="856" id="6" val="-1" num="" desc="񡰡s" />
<dato cant="680" id="1" val="-1" num="" desc="Ra򬢠/>
<dato cant="684" id="5" val="-1" num="" desc="..?? ? ??????" />
<dato cant="1621" id="1" val="-1" num="" desc="Ra򬢠/>
<dato cant="1625" id="5" val="-1" num="" desc="Hola" />
</reg>
</prueba>
Greetings and thanks for your time.
This is a relatively common problem to encounter when using JDOM - especially in countries/regions with non-latin alphabets. In some senses I regret maintaining the use of Writer outputs at all in JDOM.
See the JavaDoc on XMLOutputter too: http://www.jdom.org/docs/apidocs/org/jdom2/output/XMLOutputter.html
The issue is that FileWriter uses the default encoding of the system to convert from the Writer to the underlying byte data. JDOM cannot control that conversion.
If you change the line of code:
xmlOutput.output(doc, new FileWriter("c:\\prueba3.xml"));
to use an OutputStream instead of a Writer:
try (OutputStream fos = new FileOutputStream("c:\\prueba3.xml")) {
xmlOutput.output(doc, fos);
}
... it will use the output as a byte-stream, and the systems' default encoding won't interfere with the output.
(P.S. There's no reason to assign the xmlOutput instance twice.)

DBUnit - integrity constraint violation: foreign key no action; SYS_FK_10556

I am currently coding test with dbunit(using hsqldb). However, I have a huge Problem at initializing the db:
here`s the code:
/**
* Init before a test starts
*/
#Before
public void initialise() {
IDataSet dataSetRating = null;
IDataSet dataSetMovie = null;
log.info("enter init test");
try {
con = datasource.getConnection();
icon = new DatabaseConnection(con);
File rating = new File("./src/test/resources/startDatabaseRating.xml");
dataSetRating = new FlatXmlDataSetBuilder().build(rating);
DatabaseOperation.CLEAN_INSERT.execute(icon, dataSetRating);
} catch (Exception e) {
e.printStackTrace();
log.error(e);
System.exit(-1);
}
}
my create statement looks like that:
CREATE TABLE Rating
(
rid INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
mid INTEGER FOREIGN KEY REFERENCES Movie(movieId),
rating INTEGER NOT NULL,
);
and my startDatabaseRating.xml looks like that:
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<Rating rid="0" mid="0" rating="1" />
<Rating rid="1" mid="0" rating="2" />
<Rating rid="2" mid="0" rating="3" />
<Rating rid="3" mid="0" rating="4" />
<Movie movieid="0" title="Movie1" moviePath="C" />
<Movie movieid="1" title="Movie2" moviePath="D" />
</dataset>
When I run the tests I get:
java.sql.SQLIntegrityConstraintViolationException: integrity
constraint violation: foreign key no action; SYS_FK_10556 table:
RATING
Why do I get this exception, cause there is still a dataset in the *.xml file. How to fix this problem?
UPDATE:
CREATE TABLE Movie
(
movieId INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title VARCHAR(255) NOT NULL,
moviePath VARCHAR(500) NOT NULL
);
When inserting a rating, the movie that is referenced must already exist in the movie table. So you are inserting the rows in the wrong order.
You need to first insert the movies, then the ratings.
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<Movie movieid="0" title="Movie1" moviePath="C" />
<Movie movieid="1" title="Movie2" moviePath="D" />
<Rating rid="0" mid="0" rating="1" />
<Rating rid="1" mid="0" rating="2" />
<Rating rid="2" mid="0" rating="3" />
<Rating rid="3" mid="0" rating="4" />
</dataset>
Also I would recommand you to use regular labels for your columns, especially for the id and the foreign key, because it is much more easier to understand and to maintain, if another person is in charge of your code some day !
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<Movie id="0" title="Movie1" moviePath="C" />
<Movie id="1" title="Movie2" moviePath="D" />
<Rating id="0" movie_id="0" rating="1" />
<Rating id="1" movie_id="0" rating="2" />
<Rating id="2" movie_id="0" rating="3" />
<Rating id="3" movie_id="0" rating="4" />
</dataset>

Categories