Submitting an XML post request using Java - java

I am trying to integrate a Usurv survey to my website. To do this, I need to submit an XML request to the URL http://app.usurv.com/API/Gateway.svc/getcampaignforframe, using HTTP POST. Then the response should contain a unique URL pointing to a survey.
Unfortunately I can't get it to work - the code compiles correctly but when I load the webpage I get the following exception:
"WARNING: URL = http://app.usurv.com/API/Gateway.svc/getcampaignforframe
[Fatal Error] CampaignFrameRequest%3E:6:3: The element type "link" must be terminated by the matching end-tag "</link>"."
I'm really confused about that as the XML doesn't even have a link
tag, so I'm not sure where the error could be coming from. Does anyone have any ideas what could be causing this and how I can fix it?
Here is the Java code:
public class UsurvSurveyElement extends RenderController
{
private static Logger LOG = Logger.getLogger(UsurvSurveyElement.class.getName());
String xml = "<CampaignFrameRequest xmlns='http://Qsurv/api' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'><PartnerId>236</PartnerId><PartnerWebsiteID>45</PartnerWebsiteID><RespondentID>1</RespondentID><RedirectUrlComplete>http://localhost:8080/eveningstar/home</RedirectUrlComplete><RedirectUrlSkip>http://localhost:8080/eveningstar/home</RedirectUrlSkip></CampaignFrameRequest>";
String strURL = "http://app.usurv.com/API/Gateway.svc/getcampaignforframe";
#Override
public void populateModelBeforeCacheKey(RenderRequest renderRequest, TopModel topModel, ControllerContext controllerContext )
{
super.populateModelBeforeCacheKey( renderRequest, topModel, controllerContext );
PostMethod post = new PostMethod(strURL);
try
{
// Specify content type and encoding
// If content encoding is not explicitly specified
// ISO-8859-1 is assumed
post.setRequestHeader(
"Content-type", "text/xml; charset=ISO-8859-1");
LOG.warning("request headers: " +post.getRequestHeader("Content-type"));
StringRequestEntity requestEntity = new StringRequestEntity(xml);
post.setRequestEntity(requestEntity);
LOG.warning("request entity: " +post.getRequestEntity());
String response = post.getResponseBodyAsString();
LOG.warning("XML string = " + xml);
LOG.warning("URL = " + strURL);
topModel.getLocal().setAttribute("thexmlresponse",response);
}
catch(Exception e)
{
LOG.warning("Errors while executing postMethod "+ e);
}
try
{
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document document = docBuilder.parse(strURL+xml);
processNode(document.getDocumentElement());
LOG.warning("doc output = " + document);
}
catch(Exception e)
{
LOG.warning("Errors while parsing XML: "+ e);
}
}
private void processNode(Node node) {
// do something with the current node instead of System.out
LOG.warning(node.getNodeName());
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
//calls this method for all the children which is Element
LOG.warning("current node: " + currentNode);
processNode(currentNode);
}
}
}
}

This line looks really strange, don't you mean to parse the response body instead?
Document document = docBuilder.parse(strURL+xml);
The parse method with a string parameter uses this string as an URL, so the XML parser is connection to the server again, using a GET request. The server is probably responding with an error message in HTML format, leading to the exception complaining about the link element.
Something like the following should work better:
Document document = docBuilder.parse(new InputSource(new StringReader(response)));

Related

Retrieve XML Element names with Java from unknown message format

I am parsing XML from lots of JMS messaging topics, so the structure of each message varies a lot and I'd like to make one general tool to parse them all.
To start, all I want to do is get the element names:
<gui-action>
<action>some action</action>
<params>
<param1>blue</param1>
<param2>tall</param2>
<params>
</gui-action>
I just want to retrieve the strings "gui-action", "action", "params", "param1", and "param2." Duplicates are just fine.
I've tried using org.w3c.dom.Node, Element, NodeLists and I'm not having much luck. I keep getting the element values, not the names.
private Element root;
private Document doc;
private NodeList nl;
//messageStr is passed in elsewhere in the code
//but is a string of the full XML message.
doc = xmlParse( messageStr );
root = doc.getDocumentElement();
nl = root.getChildNodes();
int size = nl.getLength();
for (int i=0; i<size; i++) {
log.info( nl.item(i).getNodeName() );
}
public Document xmlParse( String xml ){
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db;
InputSource is;
try {
//Using factory get an instance of document builder
db = dbf.newDocumentBuilder();
is = new InputSource(new StringReader( xml ) );
doc = db.parse( is );
} catch(ParserConfigurationException pce) {
pce.printStackTrace();
} catch(SAXException se) {
se.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
}
return doc;
//parse using builder to get DOM representation of the XML file
}
My logged "parsed" XML looks like this:
#text
action
#text
params
#text
Figured it out. I was iterating over only the child nodes, and not including the parent. So now I just filter out the #texts, and include the parent. Derp.
log.info(root.getNodeName() );
for (int i=0; i<size; i++) {
nodeName = nl.item(i).getNodeName();
if( nodeName != "#text" ) {
log.info( nodeName );
}
}
Now if anyone knows a way to get a NodeList of the entire document, that would be awesome.

null pointer exception on getNodeValue() when parsing XML web page - android

I looked over several of the answers posted here, but I can't find the answer I need. It may have to do with the web site itself, but I don't think it is.
I'm trying to parse an XML on a web site and I'm getting a null pointer exception error.
I run the parsing is a separate thread following Google demand when reading from the web.
please see my code and try to help.
class BackgroundTask1 extends AsyncTask<String, Void, String[]> {
protected String[] doInBackground(String... url) {
new HttpGet();
new StringBuffer();
InputStream is = null;
HttpURLConnection con = null;
try {
//Log.d("eyal", "URL: " + boiUrl);
URL url1 = new URL("http://www.boi.org.il/currency.xml");
con = (HttpURLConnection)url1.openConnection();
con.setRequestMethod("GET");
con.connect();
is = con.getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
NodeList lastVld = doc.getElementsByTagName("LAST_UPDATE");
String lastV = lastVld.item(0).getFirstChild().getNodeValue();
}
catch (Exception e) {
e.printStackTrace();
}
I get the error on the last line.
Thanks for your help.
This code worked for me
InputStream is = null;
HttpURLConnection con = null;
try {
URL url1 = new URL("http://www.boi.org.il/currency.xml");
con = (HttpURLConnection)url1.openConnection();
con.setRequestMethod("GET");
con.connect();
is = con.getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
NodeList lastVld = doc.getElementsByTagName("LAST_UPDATE");
Element elem = (Element) lastVld.item(0);
String lastV = elem.getTextContent();
System.out.println(lastV);
} catch (Exception e) {
e.printStackTrace();
}
I verified I was getting good content by adding a transformer to print out the results to the console.
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer xform = tFactory.newTransformer();
xform.transform(new DOMSource(doc), new StreamResult(System.out));
There was a couple times I tried running where elem came out null, which I think had something to do with some bad content being retrieved from the URL. This was the content that was printed by the transformer.
<html>
<body>
<script>document.cookie='iiiiiii=11a887d6iiiiiii_11a887d6; path=/';window.location.href=window.location.href;</script>
</body>
</html>
I noticed that if I had this file open in my browser, the code would all of a sudden quit working until I refreshed the page, then it started giving me the right output.
I suspect there's an issue with something at this URL, because when it works properly, this code works fine.
Good luck...
You only have one LAST_UPDATE tag in your xml and it has an inner value, so try just using the node value from the Node Class you get from item(0)
String lastV = lastVld.item(0).getNodeValue();
HTHs
There is no node returned for that tag name. You may want to first check the size of the lastVld and then try to access the items in there.

How to read XML response in specific character code in Java

I use Wikimedia API Sandbox for Japanese.
Japanese Version
English Version
I send a HTTP request to Wikimedia and I get a result formed in XML.
When I try to send a request and get a result on API Sandbox Webpage, there is no character corruption in a result.
But when I get a result in Java, a result includes character corruptions.
I cannot assign a specific character code in XML file.
How can I assign a result a specific character code?
How can I resolve my problem?
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db
.parse(new URL(
"http://ja.wikipedia.org/w/api.php?action=query&prop=categories&format=xml&cllimit=10&titles="
+ key).openStream());
Element root = doc.getDocumentElement();
NodeList queryList = root.getChildNodes();
Node query = queryList.item(0);
if (query instanceof Element) {
Element queryEle = (Element) query;
NodeList pagesList = queryEle.getChildNodes();
Node pgs = pagesList.item(0);
if (pgs instanceof Element) {
Element pagesElement = (Element) pgs;
NodeList pageList = pagesElement.getChildNodes();
Node page = pageList.item(0);
if (page instanceof Element) {
Element pageElement = (Element) page;
String title = pageElement.getAttribute("title");
title = new String(title.getBytes("UTF-8"), "UTF-8");
}
}
}
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
} catch (IOException e) {
}
Now I send a request, I got a result whose page title is "大学". But in Java, it shows "??".
I use above code for Android Application.
title = new String(title.getBytes("UTF-8"), "UTF-8"); can be left out.
It worked for me, for key=1 (receiving UTF-8). I have a UTF-8 Linux PC though. Maybe you did not output in a UTF-8 context or so. Try write the Document to a file.
You could do more inspection:
URLConnection connection = new URL("...").openConnection();
... connection.getContentEncoding();
... connection.getContentType();
InputStream in = connection.openStream();

Read XHTML And Custom Tags Into DOM Tree

I am doing conversion from XHTML to PDF using flying saucer, it works perfectly but now i want to add bookmarks, and according to the fs documentation it should be done like this:
<bookmarks>
<bookmark name='1. Foo bar baz' href='#1'>
<bookmark name='1.1 Baz quux' href='#1.2'>
</bookmark>
</bookmark>
<bookmark name='2. Foo bar baz' href='#2'>
<bookmark name='2.1 Baz quux' href='#2.2'>
</bookmark>
</bookmark>
</bookmarks>
That should be put into the HEAD section, I have done that but the SAXParser wont read the file anymore, saying:
line 11 column 14 - Error: <bookmarks> is not recognized!
line 11 column 25 - Error: <bookmark> is not recognized!
I have a local entity resolver set up and have even added the bookmarks to a DTD,
<!--flying saucer bookmarks -->
<!ELEMENT bookmarks (#PCDATA)>
<!ATTLIST bookmarks %attrs;>
<!ELEMENT bookmark (#PCDATA)>
<!ATTLIST bookmark %attrs;>
But it just wont parse, I am out of ideas, please help.
EDIT
I am using the following code to parse:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
builder.setEntityResolver(new LocalEntityResolver());
document = builder.parse(is);
EDIT
Here is LocalEntityResolver:
class LocalEntityResolver implements EntityResolver {
private static final Logger LOG = ESAPI.getLogger(LocalEntityResolver.class);
private static final Map<String, String> DTDS;
static {
DTDS = new HashMap<String, String>();
DTDS.put("-//W3C//DTD XHTML 1.0 Strict//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
DTDS.put("-//W3C//DTD XHTML 1.0 Transitional//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd");
DTDS.put("-//W3C//ENTITIES Latin 1 for XHTML//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent");
DTDS.put("-//W3C//ENTITIES Symbols for XHTML//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml-symbol.ent");
DTDS.put("-//W3C//ENTITIES Special for XHTML//EN",
"http://www.w3.org/TR/xhtml1/DTD/xhtml-special.ent");
}
#Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
InputSource input_source = null;
if (publicId != null && DTDS.containsKey(publicId)) {
LOG.debug(Logger.EVENT_SUCCESS, "Looking for local copy of [" + publicId + "]");
final String dtd_system_id = DTDS.get(publicId);
final String file_name = dtd_system_id.substring(
dtd_system_id.lastIndexOf('/') + 1, dtd_system_id.length());
InputStream input_stream = FileUtil.readStreamFromClasspath(
file_name, "my/class/path",
getClass().getClassLoader());
if (input_stream != null) {
LOG.debug(Logger.EVENT_SUCCESS, "Found local file [" + file_name + "]!");
input_source = new InputSource(input_stream);
}
}
return input_source;
}
}
My document builder factory implementation is :
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
Ugh, I finally found the problem. Sorry for making you guys debug the code, the problem was that in my code there was a call to JTidy.parse just before the DOM parsing occurred, this resulted in the content to be parsed to be empty and i did not even catch that, the actual Error was, Premature End of file from SAX.
Thanks to Matt Gibson, while i was going through the code to compile a short input document, i found the bug.
My code now includes a check to see if the content was null
/**
* parses String content into a valid XML document.
* #param content the content to be parsed.
* #return the parsed document or <tt>null</tt>
*/
private static Document parse(final String content) {
Document document = null;
try {
if (StringUtil.isNull(content)) {
throw new IllegalArgumentException("cannot parse null "
+ "content into a DOM object!");
}
InputStream is = new ByteArrayInputStream(content
.getBytes(CONTEXT.getEncoding()));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
builder.setEntityResolver(new LocalEntityResolver());
document = builder.parse(is);
} catch (Exception ex) {
LOG.error(Logger.EVENT_FAILURE, "parsing failed "
+ "for content[" + content + "]", ex);
}
return document;
}

HTTP 500 error when sending XML to server

I am trying to send an XML file to my RESTful web server, and receive a XML file in return, however, I am getting a 500 error.
java.io.IOException: Server returned HTTP response code: 500 for URL:
http://sps-psa-240:8080/NMCJWS/rest/jmsmon2/pub at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1436)
at SendXML.send(SendXML.java:151)
at SendXML.main(SendXML.java:39)
Line 151 is InputStream response = uc.getInputStream();
If I uncomment System.out.println(((HttpURLConnection) uc).getResponseCode());,
then I get the same error on OutputStreamWriter out = new OutputStreamWriter(uc.getOutputStream());
I know the server works because a coworker has this working in Obj-C.
Here is my code:
public class SendXML
{
public static void main(String[] args) throws SAXException, XPathExpressionException, ParserConfigurationException,
IOException, TransformerException
{
String xml = generateXML("AC24", "/fa/gdscc/dss24-apc");
send("localhost", xml);
}
public static String generateXML(String conn, String funcAddr) throws ParserConfigurationException, SAXException,
IOException, XPathExpressionException, TransformerException
{
/*
* <?xml version="1.0" encoding="UTF-8"?>
<JMSMON2Req>
<SubItem UID="iPAD-2031e616-de74-44a7-9292-3745d2b1ba21">
<FuncAddr>/fa/gdscc/con1-ac25</FuncAddr>
<ItemName>AZANG</ItemName>
<ItemName>ELANG</ItemName>
<Metadata key="UID">iPAD-2031e616-de74-44a7-9292-3745d2b1ba21</Metadata>
<Metadata key="CONN">1</Metadata>
</SubItem>
</JMSMON2Req>
*/
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("http://sps-psa-240:8080/NMCWS/rest/conn/subsys/prof?ss=" + conn + "&pt=IPAD_DASHBOARD");
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("/SubscrProf/DataItem/DataItemName");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
//build xml
Document output = builder.newDocument();
//create root
org.w3c.dom.Element root = output.createElement("JMSMON2Req");
output.appendChild(root);
//create subitem
org.w3c.dom.Element subItemNode = output.createElement("SubItem");
subItemNode.setAttribute("UID", "IPAD-CN1-DSS26-SC151-PN230-AC26");
root.appendChild(subItemNode);
//create funcAddr
org.w3c.dom.Element funcAddrNode = output.createElement("FuncAddr");
Text text = output.createTextNode(funcAddr);
funcAddrNode.appendChild(text);
subItemNode.appendChild(funcAddrNode);
//create itemname
for (int i = 0; i < nodes.getLength(); i++)
{
org.w3c.dom.Element itemNameNode = output.createElement("SubItem");
text = output.createTextNode(nodes.item(i).getTextContent());
itemNameNode.appendChild(text);
subItemNode.appendChild(itemNameNode);
}
//create metadata uid
org.w3c.dom.Element metaDataNode = output.createElement("Metadata");
metaDataNode.setAttribute("key", "UID");
text = output.createTextNode("IPAD-CN1-DSS26-SC151-PN230-AC26");
metaDataNode.appendChild(text);
subItemNode.appendChild(metaDataNode);
//create metadata conn
org.w3c.dom.Element metaDataNode2 = output.createElement("Metadata");
metaDataNode2.setAttribute("key", "CONN");
text = output.createTextNode("4");
metaDataNode2.appendChild(text);
subItemNode.appendChild(metaDataNode2);
/////////////////
//Output the XML
//set up a transformer
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
//create string from xml tree
StringWriter sw = new StringWriter();
StreamResult out = new StreamResult(sw);
DOMSource source = new DOMSource(output);
trans.transform(source, out);
String xmlString = sw.toString();
//print xml
System.out.println("Here's the xml:\n" + xmlString);
return xmlString;
}
public static void send(String urladdress, String file) throws MalformedURLException, IOException
{
String charset = "UTF-8";
String s = URLEncoder.encode(file, charset);
// Open the connection and prepare to POST
URLConnection uc = new URL(urladdress).openConnection();
uc.setDoOutput(true);
uc.setRequestProperty("Accept-Charset", charset);
uc.setRequestProperty("Content-Type","text/xml");
try
{
//System.out.println(((HttpURLConnection) uc).getResponseCode());
OutputStreamWriter out = new OutputStreamWriter(uc.getOutputStream());
out.write(s);
out.flush();
InputStream response = uc.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(response));
String line;
while ((line = r.readLine()) != null)
System.out.println(line);
out.close();
response.close();
}
catch (IOException e)
{
e.printStackTrace(); // should do real exception handling
}
}
}
I figured out my problem. I had to encode xmlString in UTF-8
Look at the logs on the server. What is causing the 500 error?
Is this a RESTful web service, or a SOAP web service you're submitting to?
Consider using some sort of XML<->Object framework like JAXB or XStream.
Consider using some sort of RESTful web service framework like Jersey or RestEasy.
Consider using some sort of SOAP framework like JAX-WS or Apache Axis
Make sure you are using the right encoding.
URLEncoder.encode is making the content safe for transfer as 'application/x-www-form-urlencoded', but you probably want to use UTF-8.
Also, new OutputStreamWriter(...) should specify the desired encoding. You are currently using the standard platform encoding which is probably iso-8859-1.
Third, don't try to mess around with URLConnection yourself, if there are plenty of libs around there, that can make you life easier.
Here is the send method done in Resty (Disclaimer: I'm the author of it). HTTPClient is another choice to consider as are other client-side libraries.
import us.monoid.web.Resty;
import static us.monoid.web.Resty.*;
Resty r = new Resty();
String result = r.text(urladdress, new Content("text/xml", file.getBytes("UTF-8"))).toString();

Categories