Parsing XML in Android - java

Hy i need to parse this XML :
<WhoisRecord xmlns="http://adam.kahtava.com/services/whois" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<DomainName>68.140.1.1</DomainName>
<RegistryData><AbuseContact><Email>abuse-mail#verizonbusiness.com</Email><Name>abuse</Name><Phone>+1-800-900-0241</Phone></AbuseContact><AdministrativeContact><Email>stephen.r.middleton#verizon.com</Email><Name>Verizon Internet Services</Name><Phone>800-243-6994</Phone></AdministrativeContact><BillingContact i:nil="true"/><CreatedDate>2002-05-13T00:00:00-04:00</CreatedDate><RawText i:nil="true"/><Registrant><Address>22001 Loudoun County Parkway</Address><City>Ashburn</City><Country>US</Country><Name>UUNET Technologies, Inc.</Name><PostalCode>20147</PostalCode><StateProv>VA</StateProv></Registrant><TechnicalContact><Email>swipper#verizonbusiness.com</Email><Name>swipper</Name><Phone>+1-800-900-0241</Phone></TechnicalContact><UpdatedDate>2004-03-16T00:00:00-05:00</UpdatedDate><ZoneContact i:nil="true"/></RegistryData></WhoisRecord>
My code looks like this:
public class XMLParser
{
String streamTitle = "";
/** Called when the activity is first created.
* #throws IOException
* #throws SAXException */
public String startparse(String xml) throws SAXException, IOException
{
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
try
{
DocumentBuilder builder = builderFactory.newDocumentBuilder();
builder.parse(xml);
}
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
return builderFactory.getAttribute("WhoisRecord").toString();
}
}
when i try to return something from startparse i simple get nothing.
XMLParser xmlpar = new XMLParser();
Log.v("Faruk TEST ", "udss:"+xmlpar.startparse(temp));
Do some one know a simple solution for this problem?

Try this i hope it is what you are looking for ...
Android: parse XML from string problems

I think that your call to builderFactory.getAttribute is wrong.
DocumentBuilder.parse() returns a Document object, and this will contain the DOM that you've just parsed. You can use this to access the elements of the XML.

Try this Working with XML-Android

Related

Java JAXB unmarshaller linked exception

Background: I am trying to parse XML into object using JAXB unmarshaller.
What I've done: I used JAXB itself to generate object classes and wrote some methods to unmarshal xml.
public void xmlParser() {
try {
Acquirer acquirer = (Acquirer) readXml(Constants.XML_PATH);
System.out.println(acquirer.getDate());
} catch (JAXBException | IOException e) {
e.printStackTrace();
}
}
/**
* Initializes of JAXB Context and Unmarshaller.
*/
private static void createContext() {
try {
jaxbContext = JAXBContext.newInstance("com.test.xml.generated");
unmarshaller = jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
e.printStackTrace();
}
}
/**
* This reads the XML file from the resources in ClassPath.
*
* #param xmlFile XML file name as String with relative ClassPath
* #return Unmarashalled XML file
* #throws JAXBException
* #throws IOException
* #throws Exception
*/
public Object readXml(String xmlFile) throws JAXBException, IOException {
if (jaxbContext == null) {
createContext();
}
InputStream stream = getClass().getClassLoader().getResourceAsStream(xmlFile);
BufferedInputStream buffredStream = new BufferedInputStream(stream);
***Error:***
Object obj = unmarshaller.unmarshal(buffredStream);
buffredStream.close();
stream.close();
return obj;
}
Error is in Object obj.....
Exception:
javax.xml.bind.UnmarshalException - with linked exception:
[java.io.IOException: Stream closed]
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:246)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:125)
What I've managed to search: I used xml validator to validate xml and it seems fine. I also saw that someone suggested not to use InputStream and etc.. So I tried using File file = new File(); nothing. Moreover I tried to check auto generated object classes, but didn't find anything suspicious. #XmlElement and Root seems to be defined just fine.
P.S. I have xsd scheme of this xml (I generated all object classes using this xsd). I even used online tools to validate them both and everything seems right.
Constants.XML_PATH = "/Acquirer.xml";
Simply change:
InputStream stream = getClass().getClassLoader().getResourceAsStream(xmlFile);
on:
InputStream stream = getClass().getResourceAsStream(xmlFile);
Because when you use getClass().getClassLoader().getResourceAsStream(xmlFile) then it returns null (does not find the resource) and BufferedInputStream then throws the IOException when providing null instead of input stream instance into constructor.

Trying to get my Java IRC Bot to parse and write to an preexisting XML file

I'm a total Java virgin, and I've been stumbling slowly but surely in developing an IRC bot for my friends. So far, I've gotten nearly all of the features in working order. But, I'm really wracking my brain over this problem here, my bot so far can reply with a link, but every week, I have to change the link in the java file manually and recompile the whole thing. So, I want it to be able to parse the pertinent values from an XML file in the same directory the bot's java files are in, and be able to update those same values through an IRC client.
import org.jibble.pircbot.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.xml.sax.*;
import org.w3c.dom.*;
public class ModBot extends PircBot {
static String inputFile = "./botdata.xml";
static String outputFile = "./botdata.xml";
public ModBot() {
setLogin("ModBot");
this.setName("ModBot");
setVersion(" ");
}
public void onMessage(String channel, String sender, String login, String hostname, String message) {
if (message.equalsIgnoreCase("!lolcat")) {
sendMessage(channel, sender + "http://i.imgur.com/4IX4cUL.jpg");
}
if (message.startsWith("!updatelolcat ")) {
if(login.equals("Mainmod"));
String changelolcat = message.substring(14);
}
}
}
And the XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE botdata [
<!ELEMENT botdata (lolcat,partytime,start,end)>
<!ELEMENT lolcat (#PCDATA)>
<!ELEMENT partytime (start,end)>
<!ELEMENT start (#PCDATA)>
<!ELEMENT end (#PCDATA)>
]>
<botdata>
<lolcat>http://i.imgur.com/4IX4cUL.jpg</lolcat>
<partytime>
<start>8:45:30</start>
<end>11:00:00</end>
</partytime>
</botdata>
What I want to do is take whatever "changelolcat" is, and overwrite the current link in the XML, and then a way to read from the same XML to send what's in "lolcat" to anyone replying "!lolcat". I've been going through xpath and jdom and stuff, and I just can't make sense of it. What I've read with methods using xpath looks promising, and I'd prefer to use it because it's prettier to read.
EDIT:
It worked, I put in
try {DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse("botdata.xml");
Node botdata = document.getElementsByTagName("botdata").item(0);
NodeList nodes = botdata.getChildNodes();
for (int i = 0; i < nodes.getLength(); i++) {
Node element = nodes.item(i);
if ("lolcat".equals(element.getNodeName())) {
element.setTextContent(changelolcat);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(document);
StreamResult streamResult = new StreamResult(new File("botdata.xml"));
transformer.transform(domSource, streamResult);
}catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException sae) {
sae.printStackTrace();
}
after String changelolcat = message.substring(14);
EDIT: I figured out how to parse from my XML to send what's in a node as a message, does this look right? I feel like I'm not supposed to keep copying the doc builder over and over in different methods
if (message.equalsIgnoreCase("!lolcat")) {
try {
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.parse(botxml);
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
String lolcat = xpath.evaluate("//lolcat", document);
sendMessage(channel, sender + lolcat);
} catch (Exception e) {
e.printStackTrace();
}
}
One way to do this would be to use the javax.xml.parsers.DocumentBuilder to parse your xml file into javax.swing.text.Document, which provides a great interface for getting and modifying individual elements and their values. You can then write the modified document back to the original file, overwriting it with the new version.
Here are some links to the relevant javadocs:
Document
DocumentBuilder
You might also want to look at the javadocs for the DocumentBuilderFactory object, which is definitely the best way to generate DocumentBuilders.

How to read a XML Document by using DocumentBuilderFactory and DocumentBuilder?

I have written the following java method to read an XML File by using DocumentBuilderFactory and DocumentBuilder:
public static Document readAndGenerateXmlFile(String path, String fileName){
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
Document xmlDocument = null;
try {
docBuilder = docBuilderFactory.newDocumentBuilder();
xmlDocument = docBuilder.parse(new File(path + fileName));
} catch (ParserConfigurationException exec) {
logger.error(exec);
} catch (SAXException exec) {
logger.error(exec);
} catch (IOException exec) {
logger.error(exec);
}
return xmlDocument;
}
Also I works with Apache Maven and using a Glassfish Application Server. The XML file, which I want to read, exists in the following path "src/main/resources/myfolder/myXmlFile.xml". The parameter for the method are "path=src/main/resources/" and "fileName=tester.xml"
The java method will be called by the following method:
#ManagedBean(name="mybean")
#SessionScoped
public class GuiBean {
#PostConstruct
public void initializeGUI(){
Document xmlDocument = MyXmlFactory.readAndGenerateXmlFile("src/main/resources/myfolder", "myXmlFile.xml" );
// other java code
}
}
But now I have the problem, that occurs an IOException during execute the java method above. I get the error message "The system could not found the named path". Also I can see, that the path will be extend by Java JVM (?) to "C:/Tools/myGlassfishServer/src/main/resources/myfolder/myXmlFile.xml".
Does anybody have an idea, why I get this errormessage? If I donĀ“t started this method on an application server, the file will be founded.

Android - Test For "Well Formed" Valid XML on import

I am importing a Standard XML on startup into my application that is used to save and recall application parameters.
The XML is updated onPause() however if the application crashes for any reason the resulting XML may not be valid.
I would like to be able to test to see if the XML is valid and if not then use generic settings.
Q: How can I test the XML to see if it is valid?
Sample XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<DecisionList>
<ExampleSet1>
<Value1> 1.0 </Value1>
</ExampleSet1>
</DecisionList>
Main Activity
public class MyActivity extends Activity implements OnItemSelectedListener{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
MyActivity_Preflight.Setup();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// .......
}
}
PreFlight Activity
public class MyActivity_Preflight {
public static void Setup() throws Exception{
try{
XPathFactory factory=XPathFactory.newInstance();
XPath xPath=factory.newXPath();
File pathTmp = new File(Environment.getExternalStorageDirectory() + "/myApp/Tmp" );
File xmlDocument = new File( pathTmp + "/tmp.xml");
/*
* Chk to see if XML is Valid Statement block Here
* if Valid then Continue
*/
InputSource inputSource = new InputSource(new FileInputStream(xmlDocument));
XPathExpression tag_Value1 = xPath.compile("/DecisionList/ExampleSet1/Value1");
String Value1 = tag_Value1.evaluate(inputSource);
GlobalVariables.setSeekBarValue1(Float.valueOf(Value1));
// if (XMLisNotValid)
// GlobalVariables.setSeekBarValue1(1.0f);
}
}
}
Thanks for your time.
You can validate using DocumentBuilderFactory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
db.parse(pathTmp + "/tmp.xml");
If XML parses then its a valid XML, if not its not a valid XML.

Make DocumentBuilder.parse ignore DTD references

When I parse my xml file (variable f) in this method, I get an error
C:\Documents and Settings\joe\Desktop\aicpcudev\OnlineModule\map.dtd (The system cannot find the path specified)
I know I do not have the dtd, nor do I need it. How can I parse this File object into a Document object while ignoring DTD reference errors?
private static Document getDoc(File f, String docId) throws Exception{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(f);
return doc;
}
Try setting features on the DocumentBuilderFactory:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
dbf.setFeature("http://xml.org/sax/features/namespaces", false);
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
...
Ultimately, I think the options are specific to the parser implementation. Here is some documentation for Xerces2 if that helps.
A similar approach to the one suggested by #anjanb
builder.setEntityResolver(new EntityResolver() {
#Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if (systemId.contains("foo.dtd")) {
return new InputSource(new StringReader(""));
} else {
return null;
}
}
});
I found that simply returning an empty InputSource worked just as well?
I found an issue where the DTD file was in the jar file along with the XML. I solved the issue based on the examples here, as follows: -
DocumentBuilder db = dbf.newDocumentBuilder();
db.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
if (systemId.contains("doc.dtd")) {
InputStream dtdStream = MyClass.class
.getResourceAsStream("/my/package/doc.dtd");
return new InputSource(dtdStream);
} else {
return null;
}
}
});
Source XML (With DTD)
<!DOCTYPE MYSERVICE SYSTEM "./MYSERVICE.DTD">
<MYACCSERVICE>
<REQ_PAYLOAD>
<ACCOUNT>1234567890</ACCOUNT>
<BRANCH>001</BRANCH>
<CURRENCY>USD</CURRENCY>
<TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
</REQ_PAYLOAD>
</MYACCSERVICE>
Java DOM implementation for accepting above XML as String and removing DTD declaration
public Document removeDTDFromXML(String payload) throws Exception {
System.out.println("### Payload received in XMlDTDRemover: " + payload);
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
dbf.setValidating(false);
dbf.setNamespaceAware(true);
dbf.setFeature("http://xml.org/sax/features/namespaces", false);
dbf.setFeature("http://xml.org/sax/features/validation", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(payload));
doc = db.parse(is);
} catch (ParserConfigurationException e) {
System.out.println("Parse Error: " + e.getMessage());
return null;
} catch (SAXException e) {
System.out.println("SAX Error: " + e.getMessage());
return null;
} catch (IOException e) {
System.out.println("IO Error: " + e.getMessage());
return null;
}
return doc;
}
Destination XML (Without DTD)
<MYACCSERVICE>
<REQ_PAYLOAD>
<ACCOUNT>1234567890</ACCOUNT>
<BRANCH>001</BRANCH>
<CURRENCY>USD</CURRENCY>
<TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
</REQ_PAYLOAD>
</MYACCSERVICE>
I know I do not have the dtd, nor do I need it.
I am suspicious of this statement; does your document contain any entity references? If so, you definitely need the DTD.
Anyway, the usual way of preventing this from happening is using an XML catalog to define a local path for "map.dtd".
here's another user who got the same issue : http://forums.sun.com/thread.jspa?threadID=284209&forumID=34
user ddssot on that post says
myDocumentBuilder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId)
throws SAXException, java.io.IOException
{
if (publicId.equals("--myDTDpublicID--"))
// this deactivates the open office DTD
return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));
else return null;
}
});
The user further mentions "As you can see, when the parser hits the DTD, the entity resolver is called. I recognize my DTD with its specific ID and return an empty XML doc instead of the real DTD, stopping all validation..."
Hope this helps.
I'm working with sonarqube, and sonarlint for eclipse showed me Untrusted XML should be parsed without resolving external data (squid:S2755)
I managed to solve it using:
factory = DocumentBuilderFactory.newInstance();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// If you can't completely disable DTDs, then at least do the following:
// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
// JDK7+ - http://xml.org/sax/features/external-general-entities
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
// JDK7+ - http://xml.org/sax/features/external-parameter-entities
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// Disable external DTDs as well
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);

Categories