How I can update special element in JAXB? - java

I used Jaxb for read and write from my XML File.I want update spacial element in my XML, but I don't know how can do that in my code,any body you can till me how I can do that.
That my update method
public boolean Update(Layer entity) {
try {
File file = new File(Test.PathXMl);
//read from my xml
JAXBContext jaxbContext = JAXBContext.newInstance(Project.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Project project = (Project) jaxbUnmarshaller.unmarshal(file);
// here update my XML new value but not special element
Layer layer = new Layer();
layer.setLayerName(entity.getLayerName());
layer.setOrder(entity.getOrder());
layer.setVisible(entity.isVisible());
project.getLayer().add(layer);
//write in xml file
ObjectFactory objectFactory = new ObjectFactory();
javax.xml.bind.Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(project, new FileOutputStream(Test.PathXMl));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JAXBException e) {
e.printStackTrace();
}
return false;
}
My XML file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Project xmlns="http://www.example.org/ProjectDataBase" name="name1">
<Layer idLayer="2">
<LayerName>a</LayerName>
<Order>2</Order>
<Visible>false</Visible>
</Layer>
<Layer idLayer="1">
<LayerName>add</LayerName>
<Order>1</Order>
<Visible>true</Visible>
</Layer>
</Project>
NOTE: For example I need change value in LayerName from a -->b but just in IdLayer="2"(In my code I can't select my element which I want update).Please any way for do that!!!!

Once you have unmarshalled the XML, you should perform the following check
// unmarshal Project
for(Layer layer : project.getLayer()) {
if (layer.getIdLayer().equals("2")) {
layer.setLayerName("b");
}
}
// marshal Project back to XML

Related

JAXB unmarshal: unexpected element

Background:
I am using JAXB to unmarshal XML into Java objects. Originally, I was using just JAXB to perform the unmarshal. Then a static analysis was performed on the code and a high criticality issue was raised for XML External Entity Injection. After a little research, I found a suggestion (https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXB_Unmarshaller) to use a parser configured to prevent external entities from being parsed. An example of what to do was provided:
//Disable XXE
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
//Do unmarshall operation
Source xmlSource = new SAXSource(spf.newSAXParser().getXMLReader(), new InputSource(new StringReader(xml)));
JAXBContext jc = JAXBContext.newInstance(Object.class);
Unmarshaller um = jc.createUnmarshaller();
um.unmarshal(xmlSource);
I have not done this exactly as shown, but I believe I have done the same in effect:
XMLReader reader = getXMLReader();
if (reader == null) {
logger.warn("Unable to create XML reader");
return;
}
JAXBContext context = JAXBContext.newInstance(messageClass);
Unmarshaller unmarshaller = context.createUnmarshaller();
for (File file : files) {
try {
InputSource source = new InputSource(new FileReader(file));
Source xmlSource = new SAXSource(reader, source);
JAXBElement<? extends BaseType> object =
(JAXBElement<? extends BaseType>) unmarshaller.unmarshal(xmlSource);
messages.add(object.getValue());
} catch (FileNotFoundException e) {
logger.error("Exception", e);
}
}
...
private XMLReader getXMLReader() {
SAXParserFactory factory = SAXParserFactory.newInstance();
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
} catch (SAXNotRecognizedException | SAXNotSupportedException
| ParserConfigurationException e) {
logger.error("Exception", e);
}
XMLReader reader = null;
try {
reader = factory.newSAXParser().getXMLReader();
} catch (SAXException | ParserConfigurationException e) {
logger.error("Exception", e);
}
return reader;
}
Problem:
After implementing the correction, I am now getting an unmarshal exception when the program attempts to read in XML:
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"ns1:TypeXYZ"). Expected elements are <{protected namespace URI}TypeABC>,...<{protected namespace URI}TypeXYZ>,...
Before the above fix where I was just using JAXB to unmarshal, it was able to properly parse the provided XML with no problem.
I assume that the SAX parser expects the XML to provide extra information that's missing, or that it needs to be configured to ignore whatever it's complaining about. I tried a few other "features" (http://xml.org/sax/features/namespace-prefixes=true and http://xml.org/sax/features/validation=false), but that did not resolve the problem.
I have no control over the XML schema that defines the XML types, nor do I have control over how the corresponding Java classes are generated.
Any information to help me understand what's going on and that helps me resolve this problem, would be very much appreciated.
After a little experimentation I was able to resolve the error by setting the following features:
factory.setFeature("http://xml.org/sax/features/validation", false);
factory.setFeature("http://xml.org/sax/features/namespaces", true);
factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);

StringWrite built using a JAXB Marshaller shows "<" rather than "<" when viewed using POSTMAN

I'm building a web service and application project. Service stores the data within a local XML file containing bookInfo. Web service has a method to view all the booksInfo stored inside this XML file. Therefore, to read the XML, I'm using JAXB and unmarshalling it to POJO
UnMarshalling
AllItems items = null;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(AllItems.class);
Unmarshaller unMarshaller = jaxbContext.createUnmarshaller();
FileReader fileReader = new FileReader(new File("items.xml"));
items = (AllItems) unMarshaller.unmarshal(fileReader);
//items here is an object of the supposed to be the root element
Marshalling
After this I've marshalled this to StringWrite with following code:
StringWriter stringWriter = new StringWriter();
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(items, stringWriter);
}
catch (JAXBException | FileNotFoundException e) {
e.getMessage();
}
When I view the output on the console, everything looks pretty. If, I view the output using the endpoint address on a web browser, it still looks pretty.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<allItems>
<items>
<saleInfo>
<country>AU</country>
<saleability>FOR_SALE</saleability>
</saleInfo>
<status>back order</status>
<volumeInfo>
<authors>Liz Ellis</authors>
<industryIdentifiers>
<identifier>9781760780364</identifier>
<type>ISBN_13</type>
</industryIdentifiers>
<industryIdentifiers>
<identifier>1760780367</identifier>
<type>ISBN_10</type>
</industryIdentifiers>
<publishedDate>2018-04-24</publishedDate>
<publisher>Macmillan Publishers Aus.</publisher>
<title>If At First You Don't Conceive</title>
</volumeInfo>
</items>
But problem starts when I use POSTMAN or try to view it using the web server console.
Not desired output how to make application receive "<" instead of &alt;"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<allItems>
<items>
<saleInfo>
<country>AU</country>
<saleability>FOR_SALE</saleability>
</saleInfo>
<status>back order</status>
<volumeInfo>
<authors>Liz Ellis</authors>
<industryIdentifiers>
<identifier>9781760780364</identifier>
<type>ISBN_13</type>
</industryIdentifiers>
<industryIdentifiers>
<identifier>1760780367</identifier>
<type>ISBN_10</type>
</industryIdentifiers>
<publishedDate>2018-04-24</publishedDate>
<publisher>Macmillan Publishers Aus.</publisher>
<title>If At First You Don't Conceive</title>
</volumeInfo>
</items>
</allItems>

Java parse a xml with file drop

Having the filedrop already implemented in my code, I need to parse the xml file I drop in the main().
Main()
case "XML":
text.append("Processing file type XML: "+files[i].getCanonicalPath() + "\n" );
ReadXml read_xml = new ReadXml();
read_xml.read(files[i].getCanonicalPath(), text);
break;
ReadXml.java
public class ReadXml {
ProgramDocument programDocument = new ProgramDocument();
public void read(String FILE, javax.swing.JTextArea text ) {
try {
JAXBContext context = JAXBContext.newInstance(ProgramDocument.class);
Unmarshaller u = context.createUnmarshaller();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(FILE);
Object o = u.unmarshal( doc );
doc.getDocumentElement().normalize();
text.append("Account : " +doc.getElementsByTagName("Account").item(0));
}
catch(Exception e) {
text.append("XML file not parsed correctly.\n");
}
}
}
I am not able to print anything, and when I am, I see "NULL" or just empty row or some path#numbers
I am not a developer, I just need to try opening a xml a send contents to a DB, but this is too far already.
EDIT: added part of xml
<?xml version="1.0" encoding="UTF-8"?>
<ARRCD Version="48885" Release="38">
<Identification v="ORCOZIO"/>
<Version v="013"/>
<Account v="OCTO">
<Type v="MAJO"/>
<Date v="2016-05-14"/>
</AARCD>
There are no elements tagged "Account" in the element "Account".
What you want to read here are the Attributes of Account, not other elements.
Thus you should use eElement.getAttribute("v") if you want to read attribute v, not getElementsByTagName()

How to remove some elements from XML file generated using JAXB?

I have been trying to generate XML file from lists of object of type Customer class.
Which i have done successfully.But the structure of my XML file is nested and i want to flatten it out.
Following is my XML file content:
<Customers>
<customer>
<accessRole>
<name>Customer Center</name>
<internalId>14</internalId>
</accessRole>
<aging>0.0</aging>
<category>
<name>Individual</name>
<internalId>2</internalId>
</category>
<companyName>Wolfe Electronics</companyName>
<consolAging>0.0</consolAging>
<consolBalance>0.0</consolBalance>
<consolDepositBalance>0.0</consolDepositBalance>
<consolOverdueBalance>0.0</consolOverdueBalance>
<consolUnbilledOrders>2705.23</consolUnbilledOrders>
<creditHoldOverride/>
<dateCreated>2011-06-22T12:30:00+05:30</dateCreated>
<defaultAddress>US</defaultAddress>
<displaySymbol>$</displaySymbol>
<email>suresh#ldbsystems.com</email>
<emailPreference/>
<emailTransactions>false</emailTransactions>
<entityId>A Wolfe</entityId>
<entityStatus>
<name>CUSTOMER-Closed Won</name>
<internalId>13</internalId>
</entityStatus>
<externalId>entity-5</externalId>
<faxTransactions>false</faxTransactions>
<firstName>A</firstName>
<firstVisit>2012-02-25T05:43:18+05:30</firstVisit>
<giveAccess>true</giveAccess>
<globalSubscriptionStatus/>
<internalId>-5</internalId>
<isBudgetApproved>false</isBudgetApproved>
<isInactive>false</isInactive>
<isPerson>true</isPerson>
<lastModifiedDate>2012-12-19T07:12:03+05:30</lastModifiedDate>
<lastName>Wolfe</lastName>
<lastPageVisited>login-register</lastPageVisited>
<lastVisit>2013-02-23T06:10:44+05:30</lastVisit>
<overrideCurrencyFormat>false</overrideCurrencyFormat>
<phone>650-555-9788</phone>
<priceLevel>
<name>Employee Price</name>
<internalId>3</internalId>
</priceLevel>
<printTransactions>false</printTransactions>
<receivablesAccount>
<name>Use System Preference</name>
<internalId>-10</internalId>
</receivablesAccount>
<salesRep>
<name>Clark Koozer</name>
<internalId>23</internalId>
</salesRep>
<shipComplete>false</shipComplete>
<stage/>
<symbolPlacement/>
<taxItem>
<name>CA-SAN MATEO</name>
<internalId>-112</internalId>
</taxItem>
<taxable>false</taxable>
<unbilledOrders>2705.23</unbilledOrders>
<visits>150</visits>
<webLead>No</webLead>
</customer>
<customer>
<accessRole>
<name>Customer Center</name>
<internalId>14</internalId>
</accessRole>
<aging>0.0</aging>
<category>
<name>Corporate</name>
<internalId>1</internalId>
</category>
<consolAging>0.0</consolAging>
<consolBalance>0.0</consolBalance>
<consolDepositBalance>0.0</consolDepositBalance>
<consolOverdueBalance>0.0</consolOverdueBalance>
<consolUnbilledOrders>76.8</consolUnbilledOrders>
<creditHoldOverride/>
<customFieldList>
<customField/>
</customFieldList>
<dateCreated>2011-06-26T12:30:00+05:30</dateCreated>
<defaultAddress>Anderson Boughton Inc.<br>1488 Main<br>Apt 113<br>Seattle WA 98106<br>US</defaultAddress>
<displaySymbol>$</displaySymbol>
<email>boughton751#cscatering.com</email>
<emailPreference/>
<emailTransactions>false</emailTransactions>
<entityId>Anderson Boughton Inc.</entityId>
<entityStatus>
<name>CUSTOMER-Closed Won</name>
<internalId>13</internalId>
</entityStatus>
<faxTransactions>false</faxTransactions>
<firstVisit>2012-07-12T01:30:49+05:30</firstVisit>
<giveAccess>false</giveAccess>
<globalSubscriptionStatus/>
<internalId>75</internalId>
<isBudgetApproved>false</isBudgetApproved>
<isInactive>false</isInactive>
<isPerson>false</isPerson>
<lastModifiedDate>2012-12-19T11:50:14+05:30</lastModifiedDate>
<lastPageVisited>HP xw4100</lastPageVisited>
<lastVisit>2012-07-12T01:30:49+05:30</lastVisit>
<leadSource>
<name>Partner Referral</name>
<internalId>99993</internalId>
</leadSource>
<overrideCurrencyFormat>false</overrideCurrencyFormat>
<partner>
<name>Online electronics</name>
<internalId>171</internalId>
</partner>
<phone>206-555-1302</phone>
<priceLevel>
<name>Base Price</name>
<internalId>1</internalId>
</priceLevel>
<printTransactions>false</printTransactions>
<receivablesAccount>
<name>Use System Preference</name>
<internalId>-10</internalId>
</receivablesAccount>
<salesRep>
<name>A Wolfe</name>
<internalId>-5</internalId>
</salesRep>
<shipComplete>false</shipComplete>
<stage/>
<symbolPlacement/>
<taxable>false</taxable>
<unbilledOrders>76.8</unbilledOrders>
<webLead>No</webLead>
</customer>
</Customers>
So i have nested structure for <accessRole> which i want to flatten out like
<accessRole-name>and i don't want to display element like <internalId>.
Please find a code snippet of my model:
try {
FileWriter fileWriter = new FileWriter ("D:\\adapter-framework\\Customer_XML.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(extractedRecordsArray[0].getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
fileWriter.append("<Customers>");
fileWriter.append('\n');
for(int i = 0; i < extractedRecordsArray.length - 761 ; i++)
{
jaxbMarshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//jaxbMarshaller.marshal(extractedRecordsArray[i],fileWriter);
jaxbMarshaller.marshal(extractedRecordsArray[i],System.out);
fileWriter.append('\n');
AdapterLogger.debug(this.getClass().getName(), "Extracted record number : " + i);
}
fileWriter.append("</Customers>");
fileWriter.close();
} catch (JAXBException e) {
e.printStackTrace();
}
Please help me out if someone knows about it.
Thanks.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You can use the #XmlPath extension in MOXy to flatten the XML structure.
Customer
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
#XmlPath(".")
private AccessRole accessRole;
}
AccessRole
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class AccessRole {
#XmlElement(name="accessRoleName")
private String name;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html

validation a xml with several xsd schema DOM java

After search on internet and in differnets forums, have not found my answer.
I have a XML file which is define by two XSD schema.
For write the XML file, there are two ways to write the XML file :
(I have to delete the "<" charactere to display the XML file)
First methode to write it :
?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Policy xmlns="http://www.W3C.com/Policy/v3#" xmlns:ns2="http://www.W3C.com /PolicyExtension/v3#">
DigestAlg Algorithm="http://test"/>
Transforms>
Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n20010315"></Transform>
/Transforms>
ns2:Validation>
ns2:ConditionID>1.0.1</ns2:ConditionID>
ns2:TConditionID>1.0.2</ns2:TConditionID>
/ns2:Validation>
/Policy>"
second methodes :
?xml version="1.0" encoding="UTF-8" standalone="yes"?>
Policy xmlns="http://www.W3C.com/Policy/v3#">
DigestAlg Algorithm="http://test"/>
Transforms>
Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n20010315"></Transform>
/Transforms>
Validation xmlns:ns2="http://www.W3C.com/PolicyExtension/v3#">
ConditionID>1.0.1</ns2:ConditionID>
TConditionID>1.0.2</ns2:TConditionID>
/Validation>
/Policy>
For pasring my XML files, i use :
InputStream doc = new FileInputStream(myXMLFile);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
List<Source> sourceListSchema = new ArrayList<Source>();
sourceListSchema.add(new StreamSource(SignaturePolicy.class.getResourceAsStream(MY_XSD_SCHEMA_1)));
sourceListSchema.add(new StreamSource(SignaturePolicy.class.getResourceAsStream(MY_XSD_SCHEMA_2)));
Schema schema;
try {
Source[] sourceTmp = new Source[1];
schema = sf.newSchema(sourceListSchema.toArray(sourceTmp));
} catch (SAXException e) {
LogMachine.logger.severe(
"SAXException : The schema can not be parse :"+e.getMessage());
}
dbf.setIgnoringElementContentWhitespace(true);
dbf.setNamespaceAware(true);
dbf.setIgnoringComments(true);
dbf.setSchema(schema);
DocumentBuilder db;
try {
db = dbf.newDocumentBuilder();
documentPolicy = db.parse(Doc);
} catch (ParserConfigurationException e) {
LogMachine.logger.severe(
"ParserConfigurationException : the file can not be parse by DOM :"+e.getMessage());
} catch (SAXException e) {
LogMachine.logger.severe(
"SAXException : the file can not be parse by DOM :"+e.getMessage());
} catch (IOException e) {
LogMachine.logger.severe(
"IOException : the file can not be open like a file :"+e.getMessage());
}
When I want to parse this documents with DOM, the first XML file display an error
Exception in thread "main" org.w3c.dom.ls.LSException: The prefix "ns2" for element "ns2:Validation" is not bound.
But the second XML file is well parse.
Someone can help me to parse the two documents ??
Thank you for you help

Categories

Resources