this is my xml :
<-tobject.subject tobject.subject.refnum="01016000" />
<-tobject.subject tobject.subject.refnum="10004000" />
I want to extract 01016000 and 10004000 from it .
I used this code:
NodeList nodeLst4 = doc.getElementsByTagName("tobject.subject");
if (nodeLst4 != null) {
int numberofCOdes = nodeLst4.getLength();
aSubjectCodes = new String[numberofCOdes];
for (int i = 0; i < numberofCOdes; i++) {
XPath xpath = XPathFactory.newInstance().newXPath();
aSubjectCodes[i] = xpath.evaluate("//tobject.subject/#tobject.subject.refnum", doc);
the problem is that when i loop through it the evaluate method just return first number and do not give me the second value.
and i am not sure if using xpath.evaluate is good idea or not.
Thanks
there is no need to use the doc.getElementsByTagName.
You are mixing plain DOM with XPath.
Your xpath is correct:
package net.davymeers;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class XpathTest {
private static String XMLSTRING = "<data>"
+ "<tobject.subject tobject.subject.refnum=\"01016000\" />\r\n"
+ "\r\n"
+ "<tobject.subject tobject.subject.refnum=\"10004000\" />"
+ "</data>";
/**
* #param args
*/
public static void main(final String[] args) {
final Document doc = createDocument();
final XPath xpath = createXpath();
final NodeList nodes = findElements(
"//tobject.subject/#tobject.subject.refnum", doc, xpath);
final Collection<String> results = convertToCollection(nodes);
for (final String result : results) {
System.out.println(result);
}
}
private static Document createDocument() {
Document doc = null;
try {
final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
.newInstance();
documentBuilderFactory.setNamespaceAware(true); // never forget
// this!
final DocumentBuilder builder = documentBuilderFactory
.newDocumentBuilder();
doc = builder.parse(new ByteArrayInputStream(XMLSTRING
.getBytes("ISO-8859-1")));
} catch (final UnsupportedEncodingException exception) {
// TODO handle exception
} catch (final SAXException exception) {
// TODO handle exception
} catch (final IOException exception) {
// TODO handle exception
} catch (final ParserConfigurationException exception) {
// TODO handle exception
}
return doc;
}
private static XPath createXpath() {
final XPathFactory xpathFactory = XPathFactory.newInstance();
final XPath xpath = xpathFactory.newXPath();
return xpath;
}
private static NodeList findElements(final String xpathExpression,
final Document doc, final XPath xpath) {
NodeList nodes = null;
if (doc != null) {
try {
final XPathExpression expr = xpath.compile(xpathExpression);
final Object result = expr
.evaluate(doc, XPathConstants.NODESET);
nodes = (NodeList) result;
} catch (final XPathExpressionException exception) {
// TODO handle exception
}
}
return nodes;
}
private static Collection<String> convertToCollection(final NodeList nodes) {
final Collection<String> result = new ArrayList<String>();
if (nodes != null) {
for (int i = 0; i < nodes.getLength(); i++) {
result.add(nodes.item(i).getNodeValue());
}
}
return result;
}
}
Here's a useful class I found a while back for XMLFiles. Takes a lot of the work off of your shoulders.
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* XMLFile.java
*
* XML file object that represents an xml file and its properties. Used to
* simplify the process of reading from and writing to XML files.
*
* Derived from unknown source. Implemented on 12/03/09. Permission given to
* implement and modify code.
*/
public class XMLFile {
private String name;
private String content;
private Map<String, String> nameAttributes = new HashMap<String, String>();
private Map<String, List<XMLFile>> nameChildren = new HashMap<String, List<XMLFile>>();
private static Element rootElement(String filename, String rootName) {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filename);
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(fileInputStream);
Element rootElement = document.getDocumentElement();
if (!rootElement.getNodeName().equals(rootName))
throw new RuntimeException("Could not find root node: "
+ rootName);
return rootElement;
} catch (Exception exception) {
throw new RuntimeException(exception);
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
}
}
/**
* #param (String) Filepath of XML File (String) Root of XML File
**/
public XMLFile(String filename, String rootName) {
this(rootElement(filename, rootName));
}
/**
* #param (Element) XML File Element
**/
private XMLFile(Element element) {
this.name = element.getNodeName();
this.content = element.getTextContent();
NamedNodeMap namedNodeMap = element.getAttributes();
int n = namedNodeMap.getLength();
for (int i = 0; i < n; i++) {
Node node = namedNodeMap.item(i);
String name = node.getNodeName();
addAttribute(name, node.getNodeValue());
}
NodeList nodes = element.getChildNodes();
n = nodes.getLength();
for (int i = 0; i < n; i++) {
Node node = nodes.item(i);
int type = node.getNodeType();
if (type == Node.ELEMENT_NODE)
addChild(node.getNodeName(), new XMLFile((Element) node));
}
}
/**
* Adds attribute to ???
*
* #param (String) Attribute Name (String) Attribute Value
**/
private void addAttribute(String name, String value) {
nameAttributes.put(name, value);
}
/**
* Adds child directory to ???
*
* #param (String) Name of New Child Directory (XMLFile) XML Documentation
* of Child
**/
private void addChild(String name, XMLFile child) {
List<XMLFile> children = nameChildren.get(name);
if (children == null) {
children = new ArrayList<XMLFile>();
nameChildren.put(name, children);
}
children.add(child);
}
public String name() {
return name;
}
public String content() {
return content;
}
/**
*
**/
public XMLFile child(String name) {
List<XMLFile> children = children(name);
if (children.size() != 1)
throw new RuntimeException("Could not find individual child node: "
+ name);
return children.get(0);
}
/**
*
**/
public List<XMLFile> children(String name) {
List<XMLFile> children = nameChildren.get(name);
return children == null ? new ArrayList<XMLFile>() : children;
}
/**
* Gets the value of a specific field and converts it to a String object
*
* #param (String) Name of Field
**/
public String string(String name) {
String value = nameAttributes.get(name);
if (value == null)
throw new RuntimeException("Could not find attribute: " + name
+ ", in node: " + this.name);
return value;
}
/**
* Gets the value of a specific field and converts it to an int
*
* #param (String) Name of Field
**/
public int integer(String name) {
return Integer.parseInt(string(name));
}
/**
* Gets the value of a specific field and converts it to an
* ArrayList<String>
*
* #param (String) Name of Field
**/
public ArrayList<String> arrayListString(String name) {
String left = new String();
int finished = 0;
ArrayList<String> list = new ArrayList<String>();
try {
left = nameAttributes.get(name);
} catch (Exception e) {
System.err.println("Exception: " + e.getMessage());
}
while (finished == 0) {
if (left.indexOf(", ") > -1) {
list.add(left.substring(0, left.indexOf(", ")));
left = left.substring(left.indexOf(", ") + 2);
} else {
list.add(left);
finished = 1;
}
}
return list;
}
}
Would this work for you? I am parsing RSS XML from here:
http://www.kraftfoods.com/rss/dinnerRecipes.aspx
Look at Media and URL towards the bottom:
package recipeSearchAndFinder.xml;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DomFeedParser extends BaseFeedParser {
public DomFeedParser(String feedUrl) {
super(feedUrl);
}
public List<Message> parse() {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
List<Message> messages = new ArrayList<Message>();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document dom = builder.parse(this.getInputStream());
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName(ITEM);
for (int i = 0; i < items.getLength(); i++) {
Message message = new Message();
Node item = items.item(i);
NodeList properties = item.getChildNodes();
for (int j = 0; j < properties.getLength(); j++) {
Node property = properties.item(j);
String name = property.getNodeName();
if (name.equalsIgnoreCase(TITLE)) {
message.setTitle(property.getFirstChild()
.getNodeValue());
} else if (name.equalsIgnoreCase(LINK)) {
message.setLink(property.getFirstChild().getNodeValue());
} else if (name.equalsIgnoreCase(DESCRIPTION)) {
StringBuilder text = new StringBuilder();
NodeList chars = property.getChildNodes();
for (int k = 0; k < chars.getLength(); k++) {
text.append(chars.item(k).getNodeValue());
}
message.setDescription(text.toString());
} else if (name.equalsIgnoreCase(PUB_DATE)) {
message.setDate(property.getFirstChild().getNodeValue());
} else if (name.equalsIgnoreCase(MEDIA)) {
NamedNodeMap nMap = property.getAttributes();
String mediaurl = nMap.getNamedItem("url")
.getNodeValue();
message.setMedia(mediaurl);
}
}
messages.add(message);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
return messages;
}
}
Related
I have to generate documents in my Java Web application (Maven, runs on a server) and have to insert data from a Java class into this document.
I would like to be able to write a HTML file with placeholders. The placeholder should be replaced from the application with data from a Java class.
I also would like to be able to use conditionals like *ngFor (e.g. inserting a list into a ) or *ngIf from Angular (or attributes with a similar function).
Does anyone know a library for this?
I have a good knowledge of Java, HTML etc. so using such a library (if there is one) will not be a problem for me
In the meantime I've written a little script myself. In case someone needs something similar, I've included it in an answer
In the meantime I have searched further and unfortunately I have not found a suitable solution so far. Therefore, I have now set about programming a solution myself. Much less effort is required than expected. Here is my current code. It is currently a rough draft and certainly needs some improvement.
package com.XYZ.file.bo;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.XYZ.file.service.FileService;
import com.XYZ.servicelocator.ServiceLocator;
import com.XYZ.util.TechnicalException;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
public class TemplateGeneratorBO {
private FileService fileService;
private static final String DOC_TEMPLATE_DIR = FileBO.BASE_DIR + "templates/";
public File generateDoc(String tempFileName, String saveFolder, String saveFileName, Object entity) {
String htmlDoc = parseHtmlDoc(tempFileName, entity);
htmlDoc = replaceSpecialChars(htmlDoc);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ConverterProperties converterProperties = new ConverterProperties();
HtmlConverter.convertToPdf(htmlDoc, outStream, converterProperties);
InputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
saveFolder += "/" + callGetter(entity, "id") + "/templates";
if (!getFileService().createAndSaveFile(saveFolder, saveFileName + ".pdf", inStream)) {
int counter = 0;
boolean success = false;
do {
counter++;
success = getFileService().createAndSaveFile(saveFolder, saveFileName + "-" + counter + ".pdf",
inStream);
} while (!success);
return getFileService().getFile(saveFolder, saveFileName + "-" + counter + ".pdf");
}
return getFileService().getFile(saveFolder, saveFileName + ".pdf");
}
private String parseHtmlDoc(String fileName, Object entity) {
try {
File htmlFile = new File(DOC_TEMPLATE_DIR + fileName);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(htmlFile);
doc.getDocumentElement().normalize();
Element elm = doc.getDocumentElement();
NodeList headList = elm.getElementsByTagName("head");
NodeList bodyList = elm.getElementsByTagName("body");
verifyTemplate(fileName, elm, headList, bodyList);
Node head = headList.item(0);
String html = "<html>" + xmlToString(head) + "<body>";
html += nodeToString(bodyList.item(0),
newTempEntList(new TemplateGenEntity(entity.getClass().getSimpleName(), entity)));
html += "</body></html>";
return html;
} catch (Exception exc) {
throw new TechnicalException("DocGenerator Exception with file " + fileName, exc);
}
}
private String nodeToString(Node parentNode, List<TemplateGenEntity> entities)
throws TransformerException, ScriptException {
NodeList nodes = parentNode.getChildNodes();
StringBuilder string = new StringBuilder("");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element elm = (Element) node;
string.append(elementToString(elm, entities));
} else {
string.append(insertValues(xmlToString(node), entities));
}
}
return string.toString();
}
private String elementToString(Element elm, List<TemplateGenEntity> entities)
throws ScriptException, TransformerException {
if (!proofNgIf(elm, entities)) {
return "";
}
if (elm.hasAttribute("ngFor")) {
return ngForElementToString(elm, entities);
}
return "<" + elm.getNodeName() + getElementAttributes(elm) + ">" + nodeToString(elm, entities) + "</"
+ elm.getNodeName() + ">";
}
#SuppressWarnings("unchecked")
private String ngForElementToString(Element elm, List<TemplateGenEntity> entities)
throws ScriptException, TransformerException {
String attrs = getElementAttributes(elm);
String ngFor = elm.getAttribute("ngFor");
String[] ngForList = ngFor.split(" of ");
StringBuilder string = new StringBuilder();
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
for (TemplateGenEntity ent : entities) {
engine.put(ent.getEntityName(), ent.getEntity());
}
List<Object> list = (List<Object>) engine.eval(ngForList[1]);
for (Object obj : list) {
string.append("<" + elm.getNodeName() + attrs + ">"
+ nodeToString(elm, newTempEntList(entities, new TemplateGenEntity(ngForList[0], obj))) + "</"
+ elm.getNodeName() + ">");
}
return string.toString();
}
/**
*
* #return true if no ngIf or ngIf condition is true
* #throws ScriptException
*/
private boolean proofNgIf(Element elm, List<TemplateGenEntity> entities) throws ScriptException {
if (!elm.hasAttribute("ngIf")) {
return true;
}
String ngIf = elm.getAttribute("ngIf");
if (ngIf.isBlank()) {
throw new TechnicalException("Document template contains empty ngIf!");
}
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
for (TemplateGenEntity ent : entities) {
engine.put(ent.getEntityName(), ent.getEntity());
}
return (boolean) engine.eval(ngIf);
}
private String insertValues(String strIn, List<TemplateGenEntity> entities) throws ScriptException {
StringBuilder str = new StringBuilder(strIn);
int begin = str.indexOf("{{");
int end = str.indexOf("}}") + 2;
while (begin != -1 && end != 1) {
String var = str.substring(begin, end);
var = var.replace("{{", "");
var = var.replace("}}", "");
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
for (TemplateGenEntity ent : entities) {
engine.put(ent.getEntityName(), ent.getEntity());
}
Object val = engine.eval(var);
String valStr = objectToStr(val);
str = str.replace(begin, end, valStr);
begin = str.indexOf("{{");
end = str.indexOf("}}") + 2;
}
return str.toString();
}
private String xmlToString(Node node) throws TransformerException {
StringWriter writer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");
transformer.transform(new DOMSource(node), new StreamResult(writer));
return writer.toString();
}
private String replaceSpecialChars(String str) {
str = str.replace(">", ">");
return str;
}
private String getElementAttributes(Element elm) {
StringBuilder attrStr = new StringBuilder();
NamedNodeMap attrs = elm.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Attr attr = (Attr) attrs.item(i);
String attrName = attr.getName();
String attrVal = attr.getValue();
if (attrName.equals("ngIf") || attrName.equals("ngFor")) {
continue;
}
attrStr.append(" " + attrName + "=\"" + attrVal + "\"");
}
return attrStr.toString();
}
private void verifyTemplate(String fileName, Element elm, NodeList head, NodeList body) {
if (!elm.getNodeName().equalsIgnoreCase("html")) {
throw new TechnicalException("Document template " + fileName + " doesn't starts with html node!");
}
if (head.getLength() != 1 || head.item(0) == null) {
throw new TechnicalException("Document template " + fileName + " doesn't contains head!");
}
if (body.getLength() != 1 || head.item(0) == null) {
throw new TechnicalException("Document template " + fileName + " doesn't contains body!");
}
}
private FileService getFileService() {
if (fileService == null) {
fileService = ServiceLocator.locateService(FileService.class);
}
return fileService;
}
private Object callGetter(Object obj, String fieldName) {
PropertyDescriptor pd;
try {
pd = new PropertyDescriptor(fieldName, obj.getClass());
return pd.getReadMethod().invoke(obj);
} catch (IntrospectionException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
throw new TechnicalException(e.getMessage(), e);
}
}
private String objectToStr(Object obj) {
if (obj instanceof Date) {
return new SimpleDateFormat("dd.MM.yyyy").format(obj);
}
return obj.toString();
}
public static List<TemplateGenEntity> newTempEntList(TemplateGenEntity entity) {
List<TemplateGenEntity> list = new ArrayList<>();
list.add(entity);
return list;
}
public static List<TemplateGenEntity> newTempEntList(List<TemplateGenEntity> entities, TemplateGenEntity entity) {
List<TemplateGenEntity> list = new ArrayList<>();
for (TemplateGenEntity ent : entities) {
list.add(ent);
}
list.add(entity);
return list;
}
public class TemplateGenEntity {
private String entityName;
private Object entity;
public TemplateGenEntity(String entityName, Object entity) {
this.entityName = entityName;
this.entity = entity;
}
public String getEntityName() {
return entityName;
}
public void setEntityName(String entityName) {
this.entityName = entityName;
}
public Object getEntity() {
return entity;
}
public void setEntity(Object entity) {
this.entity = entity;
}
}
}
use freemarker for the placeholder replacement and pd4ml for the html convertion, it works well for me.
I'm building a simple currency converter which needs to sue online rates. I found the following API from the European Central Bank to use:
http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml
My problem is im struggling to implement it. Here is what i have so far after using a bunch of different sources to try and get this code together.
try{
URL url = new URL("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
NodeList nodeList1 = doc.getElementsByTagName("Cube");
for(int i = 0; i < nodeList1.getLength(); i++){
Node node = nodeList1.item(i);
}
}
catch(Exception e){
}
So what i thought is that this code would take down all the nodes which tart with "Cube", and contain the rates.
Anyone have an easier wya to pull down the rates from the API into an array in the order they appear on the XML as that's all I'm trying to do
Thanks
XPath is one way to answer this, since you just want to extract information from the XML and not change the XML. The structure of the XML suggests that you're looking for nodes that are Cube nodes, that are child of Cube which is also a child of Cube -- Cube nested three times, so extract nodes with an XPath compiled using this String: "//Cube/Cube/Cube". This looks for nodes that have Cube nested 3 times located anywhere (the //) in the Document:
XPathExpression expr = xpath.compile("//Cube/Cube/Cube");
Then check the nodes for a "currency" attribute. If they have this, then they also have a "rate" attribute, and then extract this information.
NamedNodeMap attribs = node.getAttributes();
if (attribs.getLength() > 0) {
Node currencyAttrib = attribs.getNamedItem(CURRENCY);
if (currencyAttrib != null) {
String currencyTxt = currencyAttrib.getNodeValue();
String rateTxt = attribs.getNamedItem(RATE).getNodeValue();
// ...
}
}
Where CURRENCY = "currency" and RATE = "rate"
For example:
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class TestXPath {
private static final String CURRENCY = "currency";
private static final String CUBE_NODE = "//Cube/Cube/Cube";
private static final String RATE = "rate";
public static void main(String[] args) {
List<CurrencyRate> currRateList = new ArrayList<>();
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = builderFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document document = null;
String spec = "http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
try {
URL url = new URL(spec);
InputStream is = url.openStream();
document = builder.parse(is);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
String xPathString = CUBE_NODE;
XPathExpression expr = xpath.compile(xPathString);
NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
NamedNodeMap attribs = node.getAttributes();
if (attribs.getLength() > 0) {
Node currencyAttrib = attribs.getNamedItem(CURRENCY);
if (currencyAttrib != null) {
String currencyTxt = currencyAttrib.getNodeValue();
String rateTxt = attribs.getNamedItem(RATE).getNodeValue();
currRateList.add(new CurrencyRate(currencyTxt, rateTxt));
}
}
}
} catch (SAXException | IOException | XPathExpressionException e) {
e.printStackTrace();
}
for (CurrencyRate currencyRate : currRateList) {
System.out.println(currencyRate);
}
}
}
public class CurrencyRate {
private String currency;
private String rate; // ?double
public CurrencyRate(String currency, String rate) {
super();
this.currency = currency;
this.rate = rate;
}
public String getCurrency() {
return currency;
}
public String getRate() {
return rate;
}
#Override
public String toString() {
return "CurrencyRate [currency=" + currency + ", rate=" + rate + "]";
}
// equals, hashCode,....
}
I have an html file like: http://scholar.google.gr/citations?user=v9xULZwAAAAJ&hl=el
In this file exist a table with articles. I want to get the first 20 articles (if exist) with xpath.
I try to find fist article:
String str = (String) xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody/tr[2]/td[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
And its Ok! result: Modern information retrieval
for all articles:
String str = (String) xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody/tr/td[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
but do not work
Any Idea?
Than you!
EDIT:
Also I try:
NodeList result = (NodeList)xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody/tr/td[#id='col-title']/a",
docList.get(0), XPathConstants.NODESET);
ArrayList<String>liste = new ArrayList<String>();
for(int i=0; i<result.getLength();i++){
System.out.println(result.item(i).getNodeValue());
liste.add(result.item(i).getNodeName());
}
EDIT 2 All code
Class FileOperation:
package xmlparse;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.DomSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.w3c.dom.Document;
public class FileOperations {
private static final String path = "C:\\Users\\Dimitris\\Desktop\\authors";
public ArrayList<Document> getXmlDocumt() {
ArrayList<Document> xmlFileList = new ArrayList<>();
try {
ArrayList<File> listFiles = listFiles(path);
for (File f : listFiles) {
String html = readfile(f.getAbsolutePath());
xmlFileList.add(ConvertHtml2Xml(html) );
}
} catch (IOException ex) {
Logger.getLogger(FileOperations.class.getName()).log(Level.SEVERE, null, ex);
}
return xmlFileList;
}
private ArrayList<File> listFiles(String directoryName) throws IOException {
ArrayList<File> htmlfilelist = new ArrayList<>();
File directory = new File(directoryName);
//get all the files from a directory
File[] fList = directory.listFiles();
for (File file : fList) {
if (file.isFile()) {
htmlfilelist.add(file);
}
}
return htmlfilelist;
}
private String readfile(String file) throws FileNotFoundException, IOException {
String s = "";
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
StringBuilder content = new StringBuilder(1024);
while ((s = br.readLine()) != null) {
content.append(s);
}
//System.out.println(content.toString());
return content.toString();
}
private Document ConvertHtml2Xml(String html) {
TagNode tagNode = new HtmlCleaner().clean(html);
Document doc = null;
try {
doc = new DomSerializer(new CleanerProperties()).createDOM(tagNode);
} catch (ParserConfigurationException ex) {
Logger.getLogger(FileOperations.class.getName()).log(Level.SEVERE, null, ex);
}
return doc;
}
}
Class XpathQueries:
XPath xpath;
ArrayList<Document> docList;
public XpathQueries() {
xpath = XPathFactory.newInstance().newXPath();
FileOperations fo = new FileOperations();
docList = new ArrayList<>(fo.getXmlDocumt());
}
public void getArticle() throws XPathExpressionException {
// String str = (String) xpath.evaluate("//form[contains(#id,'citationsForm')]/div[2]/div[1]/table/tbody//td[1]/a",
// docList.get(0), XPathConstants.STRING);
String str = (String) xpath.evaluate("//*[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
System.out.println(str);
}
}
Try with this:
Object result = xpath.evaluate("//*[#id='col-title']/a", docList.get(0), XPathConstants.STRING);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getNodeValue());
}
Thank you for help.
The solution is:
int length;
Object result = xpath.evaluate("//a[contains(#href,'citation_for_view')]", docList.get(0), XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
length = nodes.getLength();
if(length>20){
length=20;
}
for (int i = 0; i < length; i++) {
System.out.println(nodes.item(i).getFirstChild().getNodeValue());
}
I making a java application that give the user notification with the weather conditions.
i used the yahoo weather API provided by yahoo like that link :
http://weather.yahooapis.com/forecastrss?w=2502265
and all i have to do is to change the eight numbered code that is in the URL in order to change the city.
that's working perfect, but there are two problems facing me now:
the first one, i want to implement a lot of weather forecast sources in my application not just the yahoo weather and i can't find a similar service in any other weather forecast websites.
the second one, i want to obtain the codes of all the cities in yahoo weather as for sure i won't ask the user to enter his city code, but to enter his city name and i'll match it with the code.
and here is the code that works with me in java:
the code to return the XML file:
package search;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
public class Process {
public static void main(String[] args) throws IOException {
Display disp = new Display();
Document doc = generateXML("1940345");
disp.getConditions(doc);
}
public static Document generateXML(String code) throws IOException {
String url = null;
String XmlData = null;
// creating the URL
url = "http://weather.yahooapis.com/forecastrss?w=" + code;
URL xmlUrl = new URL(url);
InputStream in = xmlUrl.openStream();
// parsing the XmlUrl
Document doc = parse(in);
return doc;
}
public static Document parse(InputStream is) {
Document doc = null;
DocumentBuilderFactory domFactory;
DocumentBuilder builder;
try {
domFactory = DocumentBuilderFactory.newInstance();
domFactory.setValidating(false);
domFactory.setNamespaceAware(false);
builder = domFactory.newDocumentBuilder();
doc = builder.parse(is);
} catch (Exception ex) {
System.err.println("unable to load XML: " + ex);
}
return doc;
}
}
the code to display the temperature and humidity in that city :
package search;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Display {
static void getConditions(Document doc) {
String city = null;
String unit = null;
try {
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("rss");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
NodeList nl = eElement
.getElementsByTagName("yweather:location");
for (int tempr = 0; tempr < nl.getLength(); tempr++) {
Node n = nl.item(tempr);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) n;
city = e.getAttribute("city");
System.out.println("The City Is : " + city);
}
}
NodeList nl2 = eElement
.getElementsByTagName("yweather:units");
for (int tempr = 0; tempr < nl2.getLength(); tempr++) {
Node n2 = nl2.item(tempr);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element e2 = (Element) n2;
unit = e2.getAttribute("temperature");
}
}
NodeList nl3 = eElement
.getElementsByTagName("yweather:condition");
for (int tempr = 0; tempr < nl3.getLength(); tempr++) {
Node n3 = nl3.item(tempr);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element e3 = (Element) n3;
System.out.println("The Temperature In " + city
+ " Is : " + e3.getAttribute("temp") + " "
+ unit);
}
}
NodeList nl4 = eElement
.getElementsByTagName("yweather:atmosphere");
for (int tempr = 0; tempr < nl4.getLength(); tempr++) {
Node n4 = nl4.item(tempr);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element e4 = (Element) n4;
System.out.println("The Humidity In " + city
+ " Is : " + e4.getAttribute("humidity"));
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
You can use Metwit weather api simply passing latitude and longitude.
If you can implement them client-side: 200 request/day (ip based throttling) no authentication required. Worldwide coverage, JSON and REST compliant. You can register for extra API calls for free and if you still need it to call them server side the basic plan is pretty cheap.
Full disclosure: I own this API.
Take a look on this discussion. It seems relevant:
https://stackoverflow.com/questions/4876800/is-there-an-international-weather-forecast-api-that-is-not-limited-for-non-comme
Additionally type "weather forecast api" in google. There are tons of references to APIs that support several weather services.
Here's a list of Weather APIs that are available via the Temboo Java SDK:
https://temboo.com/library/keyword/weather/
You can use YQL (yahoo query language) to find the WOEID by city name like
var lclqry = escape('select * from geo.places where text="OKLAHOMA CITY"')
var lclurl = "http://query.yahooapis.com/v1/public/yql?q=" + lclqry + "&format=json&callback=?";
I know this is an old question, but i found it and as Sai suggested i have written code in java that send YQL query and retrieve WOEID number. Than it uses it to get weather from yahoo-weather-java-api. It needs gson dependecy which you can get by adding dependency to maven. I hope this will help someone.
EDIT
If there is more than one WOEID number for given town name, than getWeather returns weather for town with first WOEID returned.
CODE
Weather.java:
import com.github.fedy2.weather.YahooWeatherService;
import com.github.fedy2.weather.data.Channel;
import com.github.fedy2.weather.data.unit.DegreeUnit;
import com.google.gson.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLEncoder;
import javax.xml.bind.JAXBException;
/**
*
* #author robert
*/
public class Weather
{
public Channel getWeather(String townName) throws CantFindWeatherException
{
try
{
String baseUrl = "http://query.yahooapis.com/v1/public/yql?q=";
String query =
"select woeid from geo.places where text=\"" +
townName + "\"";
String fullUrlStr = baseUrl + URLEncoder.encode(query, "UTF-8") +
"&format=json";
URL fullUrl = new URL(fullUrlStr);
ResultObject resultObject = null;
ResultArray resultArray = null;
try (InputStream is = fullUrl.openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr))
{
String result = "";
String read;
while ((read = br.readLine()) != null)
{
result += read;
}
Gson gson = new Gson();
try
{
resultObject = gson.fromJson(result, ResultObject.class);
}
catch (com.google.gson.JsonSyntaxException ex)
{
resultArray = gson.fromJson(result, ResultArray.class);
}
}
Integer woeid = null;
if (resultObject != null)
{
if (resultObject.query.results != null)
{
woeid = resultObject.query.results.place.woeid;
}
}
else if (resultArray != null)
{
woeid = resultArray.query.results.place[0].woeid;
}
if (woeid != null)
{
YahooWeatherService service = new YahooWeatherService();
Channel channel = service.getForecast(woeid.toString(),
DegreeUnit.CELSIUS);
return channel;
}
else
{
throw new CantFindWeatherException();
}
}
catch (IOException | JsonSyntaxException | JAXBException ex)
{
throw new CantFindWeatherException(ex);
}
}
private static class ResultObject
{
public QueryObject query;
}
private static class ResultArray
{
public QueryArray query;
}
private static class QueryObject
{
public int count;
public String created;
public String lang;
public ResultsObject results;
}
private static class QueryArray
{
public int count;
public String created;
public String lang;
public ResultsArray results;
}
private static class ResultsObject
{
public Place place;
}
private static class ResultsArray
{
public Place[] place;
}
private static class Place
{
public int woeid;
}
}
CantFindWeatherException.java:
/**
*
* #author robert
*/
public class CantFindWeatherException extends Exception
{
public CantFindWeatherException()
{
}
public CantFindWeatherException(String message)
{
super(message);
}
public CantFindWeatherException(String message, Throwable cause)
{
super(message, cause);
}
public CantFindWeatherException(Throwable cause)
{
super(cause);
}
}
As for the first question, I've build a website using forecast.io. It's pretty good. Good API and 1000 free calls/day. It uses latitute/longitude to find the weather of a place.
As for the second question, I would resolve what the user puts in with the Google Geocoding Api. So when they search for "New York", you check if you already have the relevant coordinates in your database, otherwise, you do an API call to Google Geocoding.
How can i extract attribute value out of the element. My xml node is writen like this
< nodename attribute="value" > i need to extract it out to compare it against another string.
But since i am not calling document.getElementsByTag then i cant use .getAttribute("att.").getNodeValue to get the value.
Instead i have a NodeList and getAttribute() does not have getNodeValue.
package dev;
import java.io.*;
import java.util.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
public class Parser {
static String def = "\"admin\",\"base\",\"Default\",\"simple\"";
static String category = "";
static String sku = "";
static String has_options = "0";
static String name = "";
static String image = "";
static String small_image = "";
static String thumbnail = "";
public static void toCSV() {
try {
BufferedWriter output = new BufferedWriter(new FileWriter("sim.csv", true));
output.newLine();
output.write(def);
output.write(String.format(",\"%s\",\"%s\",\"%s\"", category, sku, has_options));
output.write(String.format(",\"%s\",\"%s\",\"%s\",\"%s\"", name, image, small_image, thumbnail));
output.flush();
output.close();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
toCSV();
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new File("input.asp.xml"));
document.getDocumentElement().normalize();
NodeList list = document.getElementsByTagName("izdelek");
for(int i = 0; i < 1; i++) {
NodeList child = list.item(i).getChildNodes();
for(int j = 0; j < child.getLength(); j++) {
if(child.item(j).getNodeName().equals("kategorija")) {
category = child.item(j).getTextContent().trim();
} else if(child.item(j).getNodeName().equals("ean")) {
sku = child.item(j).getTextContent().trim();
} else if(child.item(j).getNodeName().equals("izdelekIme")) {
name = child.item(j).getTextContent().trim();
} else if(child.item(j).getNodeName().equals("slikaMala")) {
small_image = child.item(j).getTextContent().trim();
thumbnail = child.item(j).getTextContent().trim();
} else if(child.item(j).getNodeName().equals("slikaVelika")) {
image = child.item(j).getTextContent().trim();
} else if(child.item(j).getNodeName().equals("dodatneLastnosti")) {
NodeList subs = child.item(j).getChildNodes();
// ^ need to parse these nodes they are written as <nodename attribute="value">
// i need to print out the value
}
}
//toCSV();
}
} catch(Exception io) {
io.printStackTrace();
}
}
}
Solved:
XML input:
< nodename attribute="value" > Something </ nodename>
Java code:
NodesList subs = child.item(j).getChildNodes();
System.out.println(subs.item(0).getTextContent()); // >> Something
Element element = (Element) document.adoptNode(subs.item(0));
System.out.println(element.getAttribute("attribute")); // >> value
You also can use this,
child.item(j).getFirstChild().getNodeValue();