I am trying to split a string twice
String example = response;
String [] array = example.split("<section>");
System.out.println(array[0]);
String [] array2 = example.split("<title>");
System.out.println(array2[2]);
I am trying to achieve this by using this code (not successfully), but instead of printing the first split i want to save it and carry on with the 2nd split. whould anyone have a solution to ths problem or better way of going about splitting a string twice? thanks
This may seem like alot... but you should really be using a DOM parser for manipulating XML:
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXParseException;
public class ExtractXML {
public static void main(String argv[]) {
DocumentBuilderFactory docBuilderFactory = null;
DocumentBuilder docBuilder = null;
Document doc = null;
String rawStr = "Response: <section><title>Input interpretation</title>"
+ "<sectioncontents>Ireland</sectioncontents></section>"
+ "<section><title>Result</title>"
+ "<sectioncontents>Michael D. Higgins</sectioncontents></section>";
String docStr = rawStr.substring(rawStr.indexOf('<'));
String answer = "";
try {
docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(new InputSource(new StringReader(docStr)));
} catch (SAXParseException e) {
System.out.println("Doc missing root node, adding and trying again...");
docStr = String.format("<root>%s</root>", docStr);
try {
doc = docBuilder.parse(new InputSource(new StringReader(docStr)));
} catch (Exception e1) {
System.out.printf("Malformed XML: %s\n", e1.getMessage());
System.exit(0);
}
} catch (Exception e) {
System.out.printf("Something went wrong: %s\n", e.getMessage());
} finally {
try {
// Normalize text representation:
doc.getDocumentElement().normalize();
NodeList titles = doc.getElementsByTagName("title");
for (int tIndex = 0; tIndex < titles.getLength(); tIndex++) {
Node node = titles.item(tIndex);
if (node.getTextContent().equals("Result")) {
Node parent = node.getParentNode();
NodeList children = parent.getChildNodes();
for (int cIndex = 0; cIndex < children.getLength(); cIndex++) {
Node child = children.item(cIndex);
if (child.getNodeName() == "sectioncontents") {
answer = child.getTextContent();
}
}
}
}
System.out.printf("Answer: %s\n", answer);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Output:
[Fatal Error] :1:98: The markup in the document following the root element must be well-formed.
Doc missing root node, adding and trying again...
Answer: Michael D. Higgins
I really don't think you want use split here. I think you want to use something like
// Extract a given tag value from an input txt.
public static String extractTagValue(String txt,
String tag) {
if (tag == null || txt == null) {
return "";
}
String lcText = txt.toLowerCase();
tag = tag.trim().toLowerCase();
String openTag = "<" + tag + ">";
String closeTag = "</" + tag + ">";
int pos1 = lcText.indexOf(openTag);
if (pos1 > -1) {
pos1 += openTag.length();
int pos2 = lcText.indexOf(closeTag, pos1 + 1);
if (pos2 > -1) {
return txt.substring(pos1, pos2);
}
}
return "";
}
public static void main(String[] args) {
String example = "<title>Hello</title><section>World</SECTION>";
String section = extractTagValue(example,
"section");
String title = extractTagValue(example, "title");
System.out.printf("%s, %s\n", title, section);
}
Which, when executed, outputs
Hello, World
Related
So I'm trying to do a five day forecast with the openweathermap api. it returns an xml of the five day forecast here
I've been trying to get the info using the code NodeList nodeList = doc.getElementsByTagName("time");. If you check the xml you'll see the tag <time> contains the forecast for every 2 hour range. but the problem is I can't seem to grab anything from inside those tags since the name is actually <tag="date range""time range" to "time range + 3hrs">.
try {
DocumentBuilderFactory dbFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(this.fiveDayForecastURL);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("time");
for (int i = 0; i < nodeList.getLength(); i++){
Node node = nodeList.item(i);
NamedNodeMap namedNodeMap = node.getAttributes();
Node attr = namedNodeMap.getNamedItem("max");
// just trying to grab anything from inside these tags
// but ideally would want min and max temp for the range
if (node.getNodeType() == Node.ELEMENT_NODE){
System.out.println(attr);
// always prints [time: null]
}
System.out.println(node);
// always prints null
}
} catch (ParserConfigurationException | IOException ex) {
ex.printStackTrace();
} catch (org.xml.sax.SAXException e) {
e.printStackTrace();
}
I'm sure I'm missing some lines of code or something but is there a way to grab everything between the time tags even though the tag names change every time? thanks
First off, I forgot how cumbersome it is to parse XML with a DOM parser.
Have you considered requesting the returned data as JSON that you can then parse with gson?
So - you're on the right track, but in order to get the min/max temperature for a given time period, you need to keep digging down in the DOM hierarchy.
temperature is a child element of time, so you'll need to grab it, then get the min and max attribute values off of it.
Something like:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
public class Test {
private static final String FIVE_DAY_FORECAST_URL =
"https://api.openweathermap.org/data/2.5/forecast?q=Denver&appid=8984d739fa91d7031fff0e84a3d2c520&mode=xml&units=imperial";
private static final String TIME_ELEM = "time";
private static final String TEMPERATURE_ELEM = "temperature";
private static final String TIME_FROM_ATTR = "from";
private static final String TIME_TO_ATTR = "to";
private static final String TEMPERATURE_MIN_ATTR = "min";
private static final String TEMPERATURE_MAX_ATTR = "max";
private static void getWeatherForcast() {
try {
final DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
final DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
final Document doc = dBuilder.parse(FIVE_DAY_FORECAST_URL);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName(TIME_ELEM);
for (int i = 0; i < nodeList.getLength(); i++) {
final Node node = nodeList.item(i);
final NamedNodeMap namedNodeMap = node.getAttributes();
final Node fromAttr = namedNodeMap.getNamedItem(TIME_FROM_ATTR);
final Node toAttr = namedNodeMap.getNamedItem(TIME_TO_ATTR);
System.out.println("Time: " + fromAttr + " " + toAttr);
final NodeList timeChildren = node.getChildNodes();
for (int j = 0; j < timeChildren.getLength(); j++) {
final Node timeChild = timeChildren.item(j);
if (TEMPERATURE_ELEM.equals(timeChild.getNodeName())) {
final NamedNodeMap temperatureAttrMap = timeChild.getAttributes();
final String minTemp = temperatureAttrMap.getNamedItem(TEMPERATURE_MIN_ATTR).getNodeValue();
final String maxTemp = temperatureAttrMap.getNamedItem(TEMPERATURE_MAX_ATTR).getNodeValue();
System.out.println("min: " + minTemp + " max: " + maxTemp);
}
}
}
} catch (ParserConfigurationException | IOException ex) {
ex.printStackTrace();
} catch (org.xml.sax.SAXException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
getWeatherForcast();
}
}
I have this xml online http://64.182.231.116/~spencerf/test.xml
And I am trying to get the two text values Assorted Cereal and Yogurt Parfait (2). Here is how I am currently parsing it, and I get the values I want as well as all the values under then, all the numbers and such, but I just want to get the names, and I am struggling how to just do that, any help or guidance would be great. Here is my code:
String currentDay = "";
String currentMeal = "";
String counter = "";
String icon1 = "";
LinkedHashMap<String, List<String>> itemsByCounter = new LinkedHashMap<String , List<String>>();
List<String> items = new ArrayList<String>();
while (eventType != XmlResourceParser.END_DOCUMENT) {
String tagName = xmlData.getName();
switch (eventType) {
case XmlResourceParser.START_TAG:
if (tagName.equalsIgnoreCase("day")) {
currentDay = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("meal")) {
currentMeal = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("counter") && currentDay.equalsIgnoreCase(day) && currentMeal.equalsIgnoreCase(meal)) {
counter = xmlData.getAttributeValue(null, "name");
}
if (tagName.equalsIgnoreCase("name") && counter != null && currentDay.equalsIgnoreCase(day) && currentMeal.equalsIgnoreCase(meal)) {
icon1 = xmlData.getAttributeValue(null, "icon1");
Log.i(TAG, "icon1: " + icon1);
}
break;
case XmlResourceParser.TEXT:
if (currentDay.equalsIgnoreCase(day) && currentMeal.equalsIgnoreCase(meal) && counter !=(null)) {
if (xmlData.getText().trim().length() > 0) {
//Here gets everything but I just want 2 names
Log.i(TAG, "data: " + xmlData.getText());
items.add(xmlData.getText().trim().replaceAll(" +", " "));
}
}
break;
case XmlPullParser.END_TAG:
if (tagName.equalsIgnoreCase("counter")) {
if (items.size() > 0) {
itemsByCounter.put(counter, items);
items = new ArrayList<String>();
recordsFound++;
}
}
break;
}
eventType = xmlData.next();
So as you can see in the comment in my code I am getting everything under the name tag, back but I just want the value of the name, and not all the other stuff.
You will need to store the name in its own child element (meaning put an end tag before the nutritional facts). Under each dish, you could have this:
<name>Assorted Cereal</name>
<nutrition_facts> ... </nutrition_facts>
Not tested but could do it along these lines:
List<Nutrition_Facts> nutrition_facts = new ArrayList<Nutrition_Facts>();
XMLDOMParser parser = new XMLDOMParser();
AssetManager manager = context.getAssets();
InputStream stream;
try {
stream = manager.open("test.xml"); //need full path to your file here - mine is stored in assets folder
Document doc = parser.getDocument(stream);
}catch(IOException ex){
System.out.printf("Error reading map %s\n", ex.getMessage());
}
NodeList nodeList = doc.getElementsByTagName("nutrition_facts");
for (int i = 0; i < nodeList.getLength(); i++) {
Element e = (Element) nodeList.item(i);
String name;
if (elementName.equals(e.getAttribute("Assorted Cereal"))){
name = e.getAttribute("name");
//do some stuff
}
}
//XMLDOMParser Class
public class XMLDOMParser {
//Returns the entire XML document
public Document getDocument(InputStream inputStream) {
Document document = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(inputStream);
document = db.parse(inputSource);
} catch (ParserConfigurationException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (SAXException e) {
Log.e("Error: ", e.getMessage());
return null;
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
return null;
}
return document;
}
/*
* I take a XML element and the tag name, look for the tag and get
* the text content i.e for <employee><name>Kumar</name></employee>
* XML snippet if the Element points to employee node and tagName
* is name I will return Kumar. Calls the private method
* getTextNodeValue(node) which returns the text value, say in our
* example Kumar. */
public String getValue(Element item, String name) {
NodeList nodes = item.getElementsByTagName(name);
return this.getTextNodeValue(nodes.item(0));
}
private final String getTextNodeValue(Node node) {
Node child;
if (node != null) {
if (node.hasChildNodes()) {
child = node.getFirstChild();
while(child != null) {
if (child.getNodeType() == Node.TEXT_NODE) {
return child.getNodeValue();
}
child = child.getNextSibling();
}
}
}
return "";
}
}
This is the task from java web services and XML:
Create a translation service.
Customer service to activate the service method as follows:
getWord ("automobil", "russian", "polish")
The first parameter is the required word, the second is the original language, and the third target language.
The method should return a string with the appropriate word or words separated by commas if there are synonyms.
Data source, the service should use XML documents (the system may have only a few words, in order to test the functionality).
This is the java doc:
package xmlparsiranje;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;
import java.util.Scanner;
public class Xmlparsiranje {
public static void main(String[] argv) throws Exception {
// try {
File fXmlFile = new File("C:\\zaTestiranje.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
Scanner word = new Scanner(System.in);
System.out.println("Input word: ");
String rijec = word.nextLine();
Scanner izvoriste = new Scanner(System.in);
System.out.println("Izvorni: ");
String izvorni = izvoriste.nextLine();
Scanner Odrediste = new Scanner(System.in);
System.out.println("Odrediste: ");
String odredisni = Odrediste.nextLine();
NodeList nList = doc.getElementsByTagName("word");
// System.out.println(odredisni);
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
Element eElement = (Element) nNode;
NodeList engleski = eElement.getElementsByTagName("english");
NodeList ruski = eElement.getElementsByTagName("russian");
NodeList poljski = eElement.getElementsByTagName("polish");
// System.out.println(engleski.item(0).getFirstChild().getTextContent());
if (odredisni.equals("english"))
{
if(izvorni.equals("russian")){
if(ruski.item(0).getFirstChild().getTextContent().equals(rijec))
{
System.out.println(ruski.item(0).getFirstChild().getTextContent());
System.out.println(engleski.item(0).getFirstChild().getTextContent());
}
}
if(izvorni.equals("polish")) {
if(poljski.item(0).getFirstChild().getTextContent().equals(rijec)) {
System.out.println(poljski.item(0).getFirstChild().getTextContent());
System.out.println(engleski.item(0).getFirstChild().getTextContent());
}
}
}
if (odredisni.equals("russian"))
{
if(izvorni.equals("english")){
if(engleski.item(0).getFirstChild().getTextContent().equals(rijec))
{
System.out.println(engleski.item(0).getFirstChild().getTextContent());
System.out.println(ruski.item(0).getFirstChild().getTextContent());
}
}
if(izvorni.equals("polish")) {
if(poljski.item(0).getFirstChild().getTextContent().equals(rijec)) {
System.out.println(poljski.item(0).getFirstChild().getTextContent());
System.out.println(ruski.item(0).getFirstChild().getTextContent());
}
}
}
if (odredisni.equals("polish"))
{
if(izvorni.equals("english")){
if(engleski.item(0).getFirstChild().getTextContent().equals(rijec))
{
System.out.println(engleski.item(0).getFirstChild().getTextContent());
System.out.println(poljski.item(0).getFirstChild().getTextContent());
}
}
if(izvorni.equals("russian")) {
if(poljski.item(0).getFirstChild().getTextContent().equals(rijec)) {
System.out.println(poljski.item(0).getFirstChild().getTextContent());
System.out.println(ruski.item(0).getFirstChild().getTextContent());
}
}
}
/* String trazenaRijec = getTagValue("english", eElement);
String engleski = getTagValue("english", eElement);
String ruski = getTagValue("russian", eElement);
String poljski = getTagValue("polish", eElement);
if (odredisni.equals(engleski))
{
System.out.println("Engleski : " + getTagValue("english", eElement));
}
if (odredisni.equals(ruski))
{
System.out.println("Ruski : " + getTagValue("russian", eElement));
}
if (odredisni.equals(poljski))
{
System.out.println("Poljski : " + getTagValue("polish", eElement));
} */
/* System.out.println("English : " + getTagValue("english", eElement));
System.out.println("Russian : " + getTagValue("russian", eElement));
System.out.println("Polish : " + getTagValue("polish", eElement));*/
}
// } catch (Exception e) {
// e.printStackTrace();
}
private static String getTagValue(String sTag, Element eElement) {
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
}
And this is XML file:
<?xml version="1.0" encoding="UTF-8"?>
<translate>
<word>
<english>Car</english>
<russian>Avtomobil</russian>
<polish>Samochod</polish>
</word>
<word>
<english>Love</english>
<russian>Lobite</russian>
<polish>milosc</polish>
</word>
<word>
<english>Busy</english>
<russian>Zanimate</russian>
<polish>Zajety</polish>
</word>
</translate>
It didnt get accepted by the instructor. He says there is no service.
What am I doing wrong?
This is a continue question from my previous question here :RSS Reader NullPointerException
In my app,in my list, sometimes i don't get the title of the RSS,and sometimes the description( and the image). The most strange here is that i don't have problem with all the links. For example,if i parse the link of the original tutorial (http://www.mobilenations.com/rss/mb.xml) everything works fine. But when i use an other link i have the above problem...
This is my DOMParser class:
package com.td.rssreader.parser;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class DOMParser {
private RSSFeed _feed = new RSSFeed();
public RSSFeed parseXml(String xml) {
// _feed.clearList();
URL url = null;
try {
url = new URL(xml);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
try {
// Create required instances
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// Parse the xml
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
// Get all <item> tags.
NodeList nl = doc.getElementsByTagName("item");
int length = nl.getLength();
for (int i = 0; i < length; i++) {
Node currentNode = nl.item(i);
RSSItem _item = new RSSItem();
NodeList nchild = currentNode.getChildNodes();
int clength = nchild.getLength();
// Get the required elements from each Item
for (int j = 1; j < clength; j = j + 2) {
Node thisNode = nchild.item(j);
String theString = null;
if (thisNode != null && thisNode.getFirstChild() != null) {
theString = thisNode.getFirstChild().getNodeValue();
}
if (theString != null) {
String nodeName = thisNode.getNodeName();
if ("title".equals(nodeName)) {
// Node name is equals to 'title' so set the Node
// value to the Title in the RSSItem.
_item.setTitle(theString);
}
else if ("description".equals(nodeName)) {
_item.setDescription(theString);
// Parse the html description to get the image url
String html = theString;
org.jsoup.nodes.Document docHtml = Jsoup
.parse(html);
Elements imgEle = docHtml.select("img");
_item.setImage(imgEle.attr("src"));
}
//description
else if ("pubDate".equals(nodeName)) {
// We replace the plus and zero's in the date with
// empty string
String formatedDate = theString.replace(" +0000",
"");
_item.setDate(formatedDate);
}
if ("link".equals(nodeName)) {
// Node name is equals to 'title' so set the Node
// value to the Title in the RSSItem.
_item.setLink(theString);
}
}
}
// add item to the list
_feed.addItem(_item);
}
} catch (Exception e) {
e.printStackTrace();
}
// Return the final feed once all the Items are added to the RSSFeed
// Object(_feed).
return _feed;
}
}
Once you are looping the through the item nodes, you then have another loop that attempts to iterate through the child elements (to set title, description, etc).
But you loop is starting at index 1 and is increasing by 2:
// Get the required elements from each Item
for (int j = 1; j < clength; j = j + 2) {
This means it only checks position 1,3,5,etc
Looking at the xml posted, that shows why you get different data each item. Set the loop to index at 0 and increase by just 1.
I got exact output what I need, but I have to use POJO class for my program, I searched lot for issue, but I didnt get clear idea.Help me to solve this issue,thanks in advance, my coding for xml pharse in java given below.
Coding for ReadAndPrintXMLFile::
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import java.net.URL;
import java.io.InputStream;
public class ReadAndPrintXMLFile{
public static void main (String argv []){
try {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
URL url = new URL("http://xxxxxxxxxxxxxxxx");
InputStream stream = url.openStream();
Document doc = docBuilder.parse(stream);
// normalize text representation
doc.getDocumentElement ().normalize ();
System.out.println ("Root element of the doc is " +
doc.getDocumentElement().getNodeName());
NodeList listOfPersons = doc.getElementsByTagName("head");
int totalPersons = listOfPersons.getLength();
System.out.println("Total no of head : " + totalPersons);
for(int s=0; s<listOfPersons.getLength() ; s++){
Node firstPersonNode = listOfPersons.item(s);
if(firstPersonNode.getNodeType() == Node.ELEMENT_NODE){
Element firstPersonElement = (Element)firstPersonNode;
//-------
NodeList firstNameList = firstPersonElement.getElementsByTagName("heading");
Element firstNameElement = (Element)firstNameList.item(0);
NodeList textFNList = firstNameElement.getChildNodes();
System.out.println("Heading : " +
((Node)textFNList.item(0)).getNodeValue().trim());
}//end of if clause
}//end of for loop with s var
}catch (SAXParseException err) {
System.out.println ("** Parsing error" + ", line "
+ err.getLineNumber () + ", uri " + err.getSystemId ());
System.out.println(" " + err.getMessage ());
}catch (SAXException e) {
Exception x = e.getException ();
((x == null) ? e : x).printStackTrace ();
}catch (Throwable t) {
t.printStackTrace ();
}
//System.exit (0);
}//end of main
}
For this xml parse program I have to POJO class, .So For this I create a class like this
public class POJOurl {
private String heading;
public String getHeading() {
return heading;
}
public void setHeading(String heading) {
this.heading = heading;
}
}
Here I dont know how to use thse get and set method in my program, using these public String getHeading() and public void setHeading(String heading) I have to execute the program.. and I have to get the output what I am getting now.. only thing is I have to use POJO class for this program
Output::
Root element of the doc is root1
Total no of head : 4
Heading : Appliance Repairs
Heading : Air conditioning and refrigeration services
Heading : Accountants
Heading : Accident Management
I would create a class Person with the attributes that you need, e.g. firstName.