I have large XML file in below format. I can read line by line and doing some string operations as I only need to extract values for a couple of fields. But, in general, how do we process file in below format ? I found Mahout XML parser, but I think it is not for below format.
<?xml version="1.0" encoding="utf-8"?>
<posts>
<row Id="1" PostTypeId="1" AcceptedAnswerId="13" CreationDate="2010-09-13T19:16:26.763" Score="155" ViewCount="160162" Body="<p>This is a common question by those who have just rooted their phones. What apps, ROMs, benefits, etc. do I get from rooting? What should I be doing now?</p>
" OwnerUserId="10" LastEditorUserId="16575" LastEditDate="2013-04-05T15:50:48.133" LastActivityDate="2013-09-03T05:57:21.440" Title="I've rooted my phone. Now what? What do I gain from rooting?" Tags="<rooting><root>" AnswerCount="2" CommentCount="0" FavoriteCount="107" CommunityOwnedDate="2011-01-25T08:44:10.820" />
<row Id="2" PostTypeId="1" AcceptedAnswerId="4" CreationDate="2010-09-13T19:17:17.917" Score="10" ViewCount="966" Body="<p>I have a Google Nexus One with Android 2.2. I didn't like the default SMS-application so I installed Handcent-SMS. Now when I get an SMS, I get notified twice. How can I fix this?</p>
" OwnerUserId="7" LastEditorUserId="981" LastEditDate="2011-11-01T18:30:32.300" LastActivityDate="2011-11-01T18:30:32.300" Title="I installed another SMS application, now I get notified twice" Tags="<2.2-froyo><sms><notifications><handcent-sms>" AnswerCount="3" FavoriteCount="2" />
</posts>
The data you have posted is from SO data dump (I know because I am currently playing with it on Hadoop). Following is the mapper I've written to create a tab separated file out of this.
You essentially read line by line and use JAXP api to parse and extract the required information
public class StackoverflowDataWranglerMapper extends Mapper<LongWritable, Text, Text, Text>
{
private final Text outputKey = new Text();
private final Text outputValue = new Text();
private final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
private DocumentBuilder builder;
private static final Joiner TAG_JOINER = Joiner.on(",").skipNulls();
// 2008-07-31T21:42:52.667
private static final DateFormat DATE_PARSER = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
private static final SimpleDateFormat DATE_BUILDER = new SimpleDateFormat("yyyy-MM-dd");
#Override
protected void setup(Context context) throws IOException, InterruptedException
{
try
{
builder = factory.newDocumentBuilder();
}
catch (ParserConfigurationException e)
{
new IOException(e);
}
}
#Override
protected void map(LongWritable inputKey, Text inputValue, Mapper<LongWritable, Text, Text, Text>.Context context)
throws IOException, InterruptedException
{
try
{
String entry = inputValue.toString();
if (entry.contains("<row "))
{
Document doc = builder.parse(new InputSource(new StringReader(entry)));
Element rootElem = doc.getDocumentElement();
String id = rootElem.getAttribute("Id");
String postedBy = rootElem.getAttribute("OwnerUserId").trim();
String viewCount = rootElem.getAttribute("ViewCount");
String postTypeId = rootElem.getAttribute("PostTypeId");
String score = rootElem.getAttribute("Score");
String title = rootElem.getAttribute("Title");
String tags = rootElem.getAttribute("Tags");
String answerCount = rootElem.getAttribute("AnswerCount");
String commentCount = rootElem.getAttribute("CommentCount");
String favoriteCount = rootElem.getAttribute("FavoriteCount");
String creationDate = rootElem.getAttribute("CreationDate");
Date parsedDate = null;
if (creationDate != null && creationDate.trim().length() > 0)
{
try
{
parsedDate = DATE_PARSER.parse(creationDate);
}
catch (ParseException e)
{
context.getCounter("Bad Record Counters", "Posts missing CreationDate").increment(1);
}
}
if (postedBy.length() == 0 || postedBy.trim().equals("-1"))
{
context.getCounter("Bad Record Counters", "Posts with either empty UserId or UserId contains '-1'")
.increment(1);
try
{
parsedDate = DATE_BUILDER.parse("2100-00-01");
}
catch (ParseException e)
{
// ignore
}
}
tags = tags.trim();
String tagTokens[] = null;
if (tags.length() > 1)
{
tagTokens = tags.substring(1, tags.length() - 1).split("><");
}
else
{
context.getCounter("Bad Record Counters", "Untagged Posts").increment(1);
}
outputKey.clear();
outputKey.set(id);
StringBuilder sb = new StringBuilder(postedBy).append("\t").append(parsedDate.getTime()).append("\t")
.append(postTypeId).append("\t").append(title).append("\t").append(viewCount).append("\t").append(score)
.append("\t");
if (tagTokens != null)
{
sb.append(TAG_JOINER.join(tagTokens)).append("\t");
}
else
{
sb.append("").append("\t");
}
sb.append(answerCount).append("\t").append(commentCount).append("\t").append(favoriteCount).toString();
outputValue.set(sb.toString());
context.write(outputKey, outputValue);
}
}
catch (SAXException e)
{
context.getCounter("Bad Record Counters", "Unparsable records").increment(1);
}
finally
{
builder.reset();
}
}
}
Related
I am developing an application that reads the XML file and creates the Hash ID based on the details present in XML. As of now, everything is working perfectly, and able to get the List<String>.
I would like to convert this application into Reactive Streams using the Smallrye Mutiny so I went through some of the documentation but did not understand clearly how to convert this application into Reactive Streams where I do not have to wait for the completion of all XML file to return the List<String>. Rather I can start returning the Multi<String> as and when the its generated.
Following is the simple XML that I am reading using SAX Parser to create the Hash ID:
<customerList>
<customer>
<name>Batman</name>
<age>25</age>
</customer>
<customer>
<name>Superman</name>
<age>28</age>
</customer>
</customerList>
Following is the Main application which will make a call to SaxHandler:
public Multi<String> xmlEventHashGenerator(final InputStream xmlStream) throws SAXException, ParserConfigurationException, IOException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
final SaxHandler saxHandler = new SaxHandler();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.newSAXParser().parse(xmlStream, saxHandler);
return Multi.createFrom().emitter(em ->{
saxHandler.getRootNodes().forEach(contextNode -> {
final String preHashString = contextNode.toString();
try {
final StringBuilder hashId = new StringBuilder();
MessageDigest.getInstance("SHA-256").digest(preHashString.getBytes(StandardCharsets.UTF_8));
hashId.append(DatatypeConverter.printHexBinary(digest).toLowerCase());
em.emit(hashId.toString());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
});
em.complete();
});
}
Following is the SaxHandler which will read the XML and create HashIDs:
public class SaxHandler extends DefaultHandler {
#Getter
private final List<String> eventHashIds = new ArrayList<>();
#Getter
private final List<ContextNode> rootNodes = new ArrayList<>();
private final HashMap<String, String> contextHeader = new HashMap<>();
private final String hashAlgorithm;
private ContextNode currentNode = null;
private ContextNode rootNode = null;
private final StringBuilder currentValue = new StringBuilder();
public SaxHandler(final String hashAlgorithm) {
this.hashAlgorithm = hashAlgorithm;
}
#Override
public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {
if (rootNode == null && qName.equals("customer")) {
rootNode = new ContextNode(contextHeader);
currentNode = rootNode;
rootNode.children.add(new ContextNode(rootNode, "type", qName));
}else if (currentNode != null) {
ContextNode n = new ContextNode(currentNode, qName, (String) null);
currentNode.children.add(n);
currentNode = n;
}
}
#Override
public void characters(char[] ch, int start, int length) {
currentValue.append(ch, start, length);
}
#Override
public void endElement(final String uri, final String localName, final String qName) {
if (rootNode != null && !qName.equals("customer")) {
final String value = !currentValue.toString().trim().equals("") ? currentValue.toString().trim() : null;
currentNode.children.add(new ContextNode(currentNode, qName, value));
}
if (qName.equals("customer")) {
rootNodes.add(rootNode);
rootNode = null;
}
currentValue.setLength(0);
}
}
Following is the Test:
#Test
public void xmlTest() throws Exception {
final HashGenerator eventHashGenerator = new HashGenerator();
final InputStream xmlStream = getClass().getResourceAsStream("/customer.xml");
final List<String> eventHashIds = eventHashGenerator.xmlHashGenerator(xmlStream, "sha3-256");
System.out.println("\nGenerated Event Hash Ids : \n" + eventHashIds);
}
Can someone please guide me to some example or provide some idea on how to convert this application into SmallRye Mutinty Multi<String> based application?
I think you can refactor xmlEventHashGenerator to
public Multi<String> xmlEventHashGenerator(final InputStream xmlStream) throws SAXException, ParserConfigurationException, IOException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
final SaxHandler saxHandler = new SaxHandler();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.newSAXParser().parse(xmlStream, saxHandler);
return Multi.createFrom()
.iterable( saxHandler.getRootNodes() )
.map( RootNode::toString )
.map( this::convertDatatype );
}
private String convertDatatype(String preHashString) {
try {
// I think we could create the MessageDigest instance only once
byte[] digest = MessageDigest.getInstance( "SHA-256" )
.digest( preHashString.getBytes( StandardCharsets.UTF_8 ) );
return DatatypeConverter.printHexBinary( digest ).toLowerCase();
}
catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException( e );
}
}
The test method will look something like:
#Test
public void xmlTest() throws Exception {
final HashGenerator eventHashGenerator = new HashGenerator();
final InputStream xmlStream = getClass().getResourceAsStream("/customer.xml");
System.out.println("Generated Event Hash Ids: ");
eventHashGenerator
.xmlHashGenerator(xmlStream)
// Print all the hash codes
.invoke( hash -> System.out.println( hash )
.await().indefinitely();
}
But if you want to concatenate all the hash codes, you can do:
#Test
public void xmlTest() throws Exception {
final HashGenerator eventHashGenerator = new HashGenerator();
final InputStream xmlStream = getClass()
.getResourceAsStream("/customer.xml");
String hash = eventHashGenerator
.xmlHashGenerator(xmlStream)
// Concatenate all the results
.collect().with( Collectors.joining() );
// Print the hashcode
.invoke( hashcode -> System.out.println("\nGenerated Event Hash Ids : \n" + hashcode) )
.await().indefinitely();
}
I am using the docx4j Java library for the first time and have some difficulties finding a good reference. What i need to start is a simple Java class to enforce the protection on a Word document in read-only mode. I have com that far that i can read the protection mode and set it. But when saving the Word document the changes are not written to the Word document.
public class Doc4JPOC {
public static void main(String[] args) {
String docName = "/Users/petervannes/Desktop/Unprotected document.docx";
// String docName = "/Users/petervannes/Desktop/Protected document.docx" ;
Doc4JPOC d4j = new Doc4JPOC();
d4j.isProtected(docName);
d4j.protect(docName);
d4j.isProtected(docName);
}
private void protect(String filename) {
try {
WordprocessingMLPackage wordMLPackage = Docx4J.load(new java.io.File(filename));
MainDocumentPart mdp = wordMLPackage.getMainDocumentPart();
Relationship rs = mdp.getRelationshipsPart().getRelationshipByType(Namespaces.SETTINGS);
DocumentSettingsPart dsp = (DocumentSettingsPart) mdp.getRelationshipsPart().getPart(rs);
// Update settings.xml
List<Object> nodes = dsp.getJAXBNodesViaXPath("//w:documentProtection", true);
for (Object obj : nodes) {
CTDocProtect cdtP = ((CTDocProtect) obj);
cdtP.setEnforcement(Boolean.TRUE);
cdtP.setEdit(STDocProtect.READ_ONLY);
}
// Write updated settings.xml to document
wordMLPackage.addTargetPart(dsp);
// wordMLPackage.save(new java.io.File(filename));
Docx4J.save(wordMLPackage, new java.io.File(filename), 0);
System.out.println("Protected document " + filename) ;
} catch (Docx4JException ex) {
Logger.getLogger(Doc4JPOC.class.getName()).log(Level.SEVERE, null, ex);
} catch (JAXBException jex) {
Logger.getLogger(Doc4JPOC.class.getName()).log(Level.SEVERE, null, jex);
}
}
private void isProtected(String filename) {
Boolean isProtectionEnforced = false;
STDocProtect editMode = STDocProtect.NONE;
try {
WordprocessingMLPackage wordMLPackage = Docx4J.load(new java.io.File(filename));
MainDocumentPart mdp = wordMLPackage.getMainDocumentPart();
Relationship rs = mdp.getRelationshipsPart().getRelationshipByType(Namespaces.SETTINGS);
DocumentSettingsPart dsp = (DocumentSettingsPart) mdp.getRelationshipsPart().getPart(rs);
System.out.println("Partname : " + dsp.getPartName());
List<Object> nodes = dsp.getJAXBNodesViaXPath("//w:documentProtection", true);
for (Object obj : nodes) {
CTDocProtect cdtP = ((CTDocProtect) obj);
isProtectionEnforced = cdtP.isEnforcement();
editMode = cdtP.getEdit();
System.out.println("Enforced: " + cdtP.isEnforcement());
System.out.println("Edit: " + cdtP.getEdit());
}
if (isProtectionEnforced) {
System.out.println("Protection is enabled , protection mode is " + editMode.toString());
} else {
System.out.println("Protection is disabled");
}
} catch (Docx4JException ex) {
Logger.getLogger(Doc4JPOC.class.getName()).log(Level.SEVERE, null, ex);
} catch (JAXBException jex) {
Logger.getLogger(Doc4JPOC.class.getName()).log(Level.SEVERE, null, jex);
}
}
}
When executing this class i do get the following output;
Partname : /word/settings.xml
Protection is disabled
Protected document /Users/petervannes/Desktop/Unprotected document.docx
Partname : /word/settings.xml
Protection is disabled
So i suspect that i am not updating the WordprocessingMLPackage or DocumentSettingsPart correctly in the protect method, but have currently no clue where it goes wrong.
Resolved it. Instead of adding the DocumentSettingsPart to the loaded WordprocessingMLPackage. The CTDocProtect instance needs to be used to set the document protection on the content.
CTDocProtect cdtP = new CTDocProtect();
cdtP.setEnforcement(Boolean.TRUE);
cdtP.setEdit(STDocProtect.READ_ONLY);
dsp.getContents().setDocumentProtection(cdtP);
Docx4J.save(wordMLPackage, new java.io.File(filename), 0);
For docx4j v3.3.0, please see http://www.docx4java.org/forums/docx-java-f6/password-set-for-documentprotection-not-accepted-in-msword-t2427.html#p8290
I'm working on small Android project in eclipse. I created a database table but instead of populating the columns using EditText control, I want to populate it using data from a file (txt or xml). I have a table shown below populated using EditText.
Database class:
#Override
public void onCreate(SQLiteDatabase sqldb) {
myTableQuery = "CREATE TABLE staff" +
"(staff_ID INTEGER PRIMARY KEY," +
"staff_Name TEXT," +
"appointment_Day TEXT," +
"start_Time TEXT," +
"end_Time TEXT," +
"comment TEXT)";
sqldb.execSQL(myTableQuery);
}
public void AddStaff(String id, String name, String day, String start, String end, String comment){
SQLiteDatabase sqldb=this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("staff_ID", id);
values.put("staff_Name", name);
values.put("appointment_Day", day);
values.put("start_Time", start);
values.put("end_Time", end);
values.put("comment", comment);
sqldb.insert("staff", null, values);
sqldb.close();
}
AddActivity class:
public void AddRowItemTable(View v){
EditText staff_id = (EditText) findViewById(R.id.sId);
EditText staff_name = (EditText) findViewById(R.id.sname);
EditText day = (EditText) findViewById(R.id.day);
EditText start = (EditText) findViewById(R.id.start);
EditText end = (EditText) findViewById(R.id.end);
EditText comment = (EditText) findViewById(R.id.comment);
String id = staff_id.getText().toString();
String name = staff_name.getText().toString();
String d = day.getText().toString();
String s = start.getText().toString();
String e = end.getText().toString();
String c = comment.getText().toString();
MainActivity.myDB.AddStaff(id, name, d, s, e, c);
Intent newintent=new Intent(this, MainActivity.class);
startActivity(newintent);
}
Instead of doing it this way, how can I read data from file to populate it. File looks like this.
<?xml version="1.0" encoding="utf-8"?>
<staff>
<record staff_ID="S1" staff_Name="John" appointment_Day="Monday" start_Time="9" end_Time="12" comment="xxx"/>
<record staff_ID="S2" staff_Name="Bob" appointment_Day="Monday" start_Time="10" end_Time="11" comment="xxx"/>
</staff>
Any help..??
Firstly, you will have to parse your xml that you have placed in the assets folder and then put those values in db. You can try looking into parsing android xml in this link. A simple pull parse code would look something like this. Here test.xml is the file name that holds you xml in the assets folder.
//File in assets folder
InputStream tinstr = null;
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
AssetManager assetManager = getAssets();
tinstr = assetManager.open("test.xml");
parser.setInput(new InputStreamReader(tinstr));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
If you want to parse your xml file, you can using XmlPullParser. For example, put your xml file (here is test.xml) in the assets folder.
and the xml file is:
<?xml version="1.0" encoding="utf-8"?>
<staff>
<record staff_ID="S1" staff_Name="John" appointment_Day="Monday" start_Time="9" end_Time="12" comment="xxx"/>
<record staff_ID="S2" staff_Name="Bob" appointment_Day="Monday" start_Time="10" end_Time="11" comment="xxx"/>
</staff>
And the code to read the xml file is:
1. firstly, you can define a class to present the data, like
public class Record{
private String staff_id;
private String staff_name;
private String appointment_day;
private int start_time;
private int end_time;
private String comment;
#Override
public boolean equals(Object o) {
// TODO Auto-generated method stub
return super.equals(o);
}
#Override
public String toString() {
// TODO Auto-generated method stub
return super.toString();
}
public String getStaff_id() {
return staff_id;
}
public void setStaff_id(String staff_id) {
this.staff_id = staff_id;
}
public String getStaff_name() {
return staff_name;
}
public void setStaff_name(String staff_name) {
this.staff_name = staff_name;
}
public String getAppointment_day() {
return appointment_day;
}
public void setAppointment_day(String appointment_day) {
this.appointment_day = appointment_day;
}
public int getStart_time() {
return start_time;
}
public void setStart_time(int start_time) {
this.start_time = start_time;
}
public int getEnd_time() {
return end_time;
}
public void setEnd_time(int end_time) {
this.end_time = end_time;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
2. In the place where you want to read the file, define
private List<Record> lists = new ArrayList<Record>();
this lists contains the record, here in this test file, there are two records to read
3. The cord to read the file:
// File in assets folder
InputStream tinstr = null;
XmlPullParserFactory factory;
try {
factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser parser = factory.newPullParser();
AssetManager assetManager = getAssets();
tinstr = assetManager.open("test.xml");
parser.setInput(new InputStreamReader(tinstr));
int eventType = parser.getEventType();
Record record = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
String xmlName = parser.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if(xmlName.endsWith("record")){
record = new Record();
record.setStart_time(Integer.valueOf(parser.getAttributeValue(null, "start_Time")));
record.setAppointment_day(parser.getAttributeValue(null, "appointment_Day"));
record.setComment(parser.getAttributeValue(null, "comment"));
record.setEnd_time(Integer.valueOf(parser.getAttributeValue(null, "end_Time")));
record.setStaff_id(parser.getAttributeValue(null, "staff_ID"));
record.setStaff_name(parser.getAttributeValue(null, "staff_Name"));
}
break;
case XmlPullParser.END_TAG:
if(xmlName.endsWith("record") && record != null){
lists.add(record);
}
break;
default:
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Hope this can help.
I made a webservice in java with a method that returns a string (a generic list in XML format). I consume this webservice from Android, and I get this string, but after several tries the Android emulator just crashes when trying to deserialize the string. This is an example for the string I get:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<peliculas>
<pelicula>
<id>18329</id>
<poster>http://cache-cmx.netmx.mx/image/muestras/5368.rrr.jpg</poster>
<titulo>007 Operación Skyfall</titulo>
</pelicula>
...
</peliculas>
This is the class in the webservice:
#XmlRootElement
public class Peliculas{
#XmlElement(name="pelicula")
protected List<Pelicula> peliculas;
public Peliculas(){ peliculas = new ArrayList<Pelicula>();}
public Peliculas(List<Pelicula> pe){
peliculas = pe;
}
public List<Pelicula> getList(){
return peliculas;
}
public void add(Pelicula pelicula) {
peliculas.add(pelicula);
}
}
________EDIT______________
Seems like you can't use JAXB with Android, and there's better/lighter libraries for that. so I tried Simple XML. This is the method:
public Peliculas unmarshal(String xml) throws Exception{
Peliculas peliculas = new Peliculas();
Serializer serializer = new Persister();
StringBuffer xmlStr = new StringBuffer( xml );
peliculas = serializer.read(Peliculas.class, ( new StringReader( xmlStr.toString() ) ) );
return peliculas;
}
BUT I get this exception, seems like it can't save data in object:
11-12 20:30:10.898: I/Error(1058): Element 'Pelicula' does not have a match in class app.cinemexservice.Pelicula at line 3
I think you are doing correct, Try this code which is given in the API.
JAXBContext jc = JAXBContext.newInstance( "add your class's full qualified class name here" );
Unmarshaller u = jc.createUnmarshaller();
Object o = u.unmarshal( xmlSource );
You can cast the Object o to your type I think. Please refer this. http://jaxb.java.net/nonav/2.2.4/docs/api/javax/xml/bind/Unmarshaller.html
I used SAX to parse the file, and then convert it manually to an object. This is the code:
public List<Pelicula> unmarshal(String xml) throws Exception{
List<Pelicula> peliculas = new ArrayList<Pelicula>();
InputStream is = new ByteArrayInputStream(xml.getBytes("UTF-8"));
XmlPullParser parser = Xml.newPullParser();
char[] c;
String id="", titulo="", poster="", atributo="";
int datos =0;
try{
parser.setInput(is, "UTF-8");
int event = parser.next();
while(event != XmlPullParser.END_DOCUMENT) {
if(event == XmlPullParser.START_TAG) {
Log.d(TAG, "<"+ parser.getName() + ">");
atributo = parser.getName();
for(int i = 0; i < parser.getAttributeCount(); i++) {
Log.d(TAG, "\t"+ parser.getAttributeName(i) + " = "+ parser.getAttributeValue(i));
}
}
if(event == XmlPullParser.TEXT&& parser.getText().trim().length() != 0)
{
Log.d(TAG, "\t\t"+ parser.getText());
if (atributo=="id"){id=parser.getText(); datos++;}
else if(atributo=="titulo"){titulo=parser.getText(); datos++;}
else if(atributo=="poster"){poster=parser.getText(); datos++;}
if(datos==3){peliculas.add(new Pelicula(id, titulo, poster)); datos=0;}
}
if(event == XmlPullParser.END_TAG)
Log.d(TAG, "</"+ parser.getName() + ">");
event = parser.next();
is.close();
}
} catch(Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); }
for (Pelicula p : peliculas){
Log.d("PelĂcula en lista: ", p.titulo);
}
return peliculas;
}
It's way too long for my taste, but I just couldn't figure out Simple XML to match my classes.
i have a class which is returning a string type value and i want to return an String array, so please tell how can i able to do that
i have an xml file like resource.xml
<prompts>
<prompt id="p1">welcome to</prompt>
<prompt id ="p2">stack overflow</prompt>
<prompt id="p3">You entered</prompt>
<prompt id="p4">the correct number</prompt>
<prompts>
i am parsing it using sax parser
public class XmlReaderPrompt {
public List<PromptBean> load(String langMode)
{
String fileName="resource.xml";
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
InputStream prompt_configfile=Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
DocumentBuilder db = null;
List<PromptBean> promptMap = new ArrayList<PromptBean>();
try {
try {
db = dbf.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
try {
doc = db.parse(prompt_configfile);
}
catch (SAXException e) {
e.printStackTrace();
}
NodeList nodeList=doc.getElementsByTagName("prompt");
for(int i=0;i<nodeList.getLength();i++)
{
Node node=nodeList.item(i);
if(node.getNodeType()==Node.ELEMENT_NODE)
{
Element element=(Element)node;
String id = element.getAttribute("id");
String name = element.getAttribute("name");
String prompt=getTextValue(element);
promptMap.add(new PromptBean(id,name,prompt));
}
}
}
catch(Exception io)
{
io.printStackTrace();
}
finally
{
db=null;
dbf=null;
}
return promptMap;
}
private String getTextValue(Element element) {
String textValue=element.getFirstChild().getTextContent().toString();
return textValue;
}
}
and a UserFunction class to return the text from the xml file
public class UserFunction{
List<PromptBean> promptObject = new ArrayList<PromptBean>();
public String getPromptFunction(String promptTag,String langMode )
{
List<PromptBean> promptObject=xrpObject.load(langMode);
for (Iterator<PromptBean> iterator = promptObject.iterator(); iterator.hasNext();){
PromptBean promptBean= (PromptBean)iterator.next();
if(promptBean.getId().equalsIgnoreCase(promptTag)){
return StringEscapeUtils.escapeXml(promptBean.getPrompt());
}
}
return null;
}
The problem is that I have to call the method getPromptFunction of UserFunction class every time I need to get text from the sub element like
String pr1 = UserFunction.getPromptFunction("p1" "resource");
String pr1 = UserFunction.getPromptFunction("p2" "resource");
String pr1 = UserFunction.getPromptFunction("p3" "resource");
and using it in jsp page as <%=pr1%>
So I want to use array like
String[] pr = UserFunction.getPromptFunction('"p1","p2","p3"' "resource")
So how I am able to do that and also tell how to use it in jsp page .
You can do it like this
public String[] getPromptFunction(String promptTag,String langMode )
{
String temp[] = new String[promptObject.size()];
List<PromptBean> promptObject=xrpObject.load(langMode);
int i = 0;
for (Iterator<PromptBean> iterator = promptObject.iterator(); iterator.hasNext();) {
PromptBean promptBean= (PromptBean)iterator.next();
if(promptBean.getId().equalsIgnoreCase(promptTag)){
temp[i] = StringEscapeUtils.escapeXml(promptBean.getPrompt());
}
i++;
}
return temp;
}