I'd like to parse a HTML code and add it to a div.
The code is as shown below:
HTMLElement targetDiv = (HTMLElement) WebMisc.getHTMLElement(webViewPanel.getWebEngine(), "targetDiv");
Document contentDocument = XMLMisc.getDocument(contentString);
Element documentElement = contentDocument.getDocumentElement();
if(documentElement != null){
NodeList list = documentElement.getChildNodes();
if(list != null && list.getLength() > 0){
for(int i = 0; i < list.getLength(); i++){
try{
targetDiv.appendChild(list.item(i));
}
catch(Exception e){
System.out.println(Misc.getStackTrace(e));
}
}
}
}
XMLMisc.java
public static Document getDocument(final String xml) throws Exception{
if(Misc.stringHasContent(xml)){
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource inputSource = new InputSource(new StringReader(xml));
Document document = builder.parse(inputSource);
document.getDocumentElement().normalize();
return document;
}
return null;
}
WebMisc.java
public static Element getHTMLElement(WebEngine webEngine, final String elementID){
//<editor-fold defaultstate="collapsed" desc="code">
if(webEngine != null && Misc.stringHasContent(elementID)){
webEngine.getDocument().normalize();
return webEngine.getDocument().getElementById(elementID);
}
return null;
//</editor-fold>
}
However, the above codes will cause the following Exception
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeferredElementImpl cannot be cast to com.sun.webkit.dom.NodeImpl
How do I fix this?
targetDiv is just a HTMLElement with the corresponding code in the HTML file
<div id="targetDiv"></div>
The following is the StackTrace
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DeferredTextImpl cannot be cast to com.sun.webkit.dom.NodeImpl
com.sun.webkit.dom.NodeImpl.getPeer(NodeImpl.java:200)
com.sun.webkit.dom.NodeImpl.appendChild(NodeImpl.java:369)
browser.JavaFXApp$3$2.run(JavaFXApp.java:527) //my application
com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:301)
com.sun.javafx.application.PlatformImpl$6$1.run(PlatformImpl.java:298)
java.security.AccessController.doPrivileged(Native Method)
com.sun.javafx.application.PlatformImpl$6.run(PlatformImpl.java:298)
com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
com.sun.glass.ui.win.WinApplication.access$300(WinApplication.java:39)
com.sun.glass.ui.win.WinApplication$4$1.run(WinApplication.java:112)
java.lang.Thread.run(Thread.java:744)
Related
public void loadSettings() {
try {
File inputFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Setting");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nList.item(temp);
NodeList VariableName = eElement.getElementsByTagName("VariableName");
NodeList VariableValue = eElement.getElementsByTagName("VariableValue");
System.out.println(VariableName.item(0).getTextContent());
if (VariableName.item(0).hasChildNodes()) {
}
// txtBookmarkUrl.setText(bookMarkUrl);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I want to make a function that gets second part of the xml in settings elements. I want the function to return a result so that i can assign it to textfield default value when the swing GUI starts. The function should take let's say 'isDecaptcher' variable name and return '0' VariableValue.
<Bookmark>
<Setting>
<VariableName>isDeathbycaptcha</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>isDecaptcher</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>isExpertdecoders</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>ManualCaptcha</VariableName>
<VariableValue>1</VariableValue>
</Setting>
</Bookmark>
public void loadSettings(String variableName) {
try {
File inputFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Setting");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nList.item(temp);
NodeList VariableName = eElement.getElementsByTagName("VariableName");
NodeList VariableValue = eElement.getElementsByTagName("VariableValue");
if (VariableName.item(0).getTextContent().equalsIgnoreCase(variableName)) {
String txtBookmarkUrlValue = VariableValue.item(0).getLastChild().getTextContent();
System.out.println(txtBookmarkUrlValue);
txtBookmarkUrl.setText(txtBookmarkUrlValue);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
This works, But if you have more robust answers you can share.
First of all create an Object wich will represent your settings. The case is to reuse it's values in whole app. I assume that you will use it only once at the beginning and settings will not change. Singleton pattern would fit there.
final class Settings{
private static volatile Settings instance = null;
private boolean _isDeathByCaptcha;
private boolean _manualCaptcha;
...
//getters & setters
public boolean isDeathByCaptcha(){
return _isDeathByCaptcha;
}
public void setIsDeathByCaptcha(boolean isDeathByCaptcha){
this._isDeathByCaptcha = isDeathByCaptcha;
}
private Settings(){}
public static Settings getInstance(){
if(instance == null){
synchronized (Settings.class) {
if (instance == null) {
instance = new Settings();
}
}
}
return instance;
}
}
After that you can call Settings.getInstance().isDeathByCaptcha(); to get your value. Of course you need to set it earlier with setter.
Full exception stack:
Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at org.apache.xerces.dom.CoreDocumentImpl.insertBefore(Unknown Source)
at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source)
at com.enniu.crawler.core.saxon.main(saxon.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
My Code:
public class saxon {
public static void main(String args[]) throws IOException, SAXException, ParserConfigurationException, XPathFactoryConfigurationException, XPathExpressionException {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = null;
builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("test.html");
Document newDoc = builder.newDocument();
XPathFactory xpf = XPathFactoryImpl.newInstance(XPathConstants.DOM_OBJECT_MODEL);
XPath xPath = xpf.newXPath();
XPathExpression compile = xPath.compile("//div[not (contains(class, 'sss'))]");
Object result = compile.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for(int i = 0; i < nodes.getLength(); i++) {
Node copyNode = newDoc.importNode(nodes.item(i), true);
newDoc.appendChild(copyNode);// line 39
}
printXmlDocument(newDoc);
}
public static void printXmlDocument(Document document) {
DOMImplementationLS domImplementationLS =
(DOMImplementationLS) document.getImplementation();
LSSerializer lsSerializer =
domImplementationLS.createLSSerializer();
String string = lsSerializer.writeToString(document);
System.out.println(string);
}
}
test.html
<table>
<div>aa</div>
<div class="sss">ss</div>
<div>dd</div>
</table>
Because a valid http document can't have two roots. My code attempt to generate document like this:
<div>aa</div>
<div>dd</div>
There are two roots in the document so get the exception.
I am making some changes to an embedded XML file in my Java application. I have some fields, a LOAD button and a SAVE button. After clicking the save button I can see the XML file updating, but after clicking the load button the old values are being loaded to the fields.
Here is my code:
public class MyLoad_SaveSampleProject {
public String field1 = "";
public String field2 = "";
public void loadSampleProject() {
InputStream file = MyLoad_SaveSampleProject.class.getResourceAsStream("/main/resources/otherClasses/projects/SampleProject.xml");
try {
DocumentBuilderFactory DocBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder DocBuilder = DocBuilderFactory.newDocumentBuilder();
Document Doc = DocBuilder.parse(file);
NodeList list = Doc.getElementsByTagName("*"); //create a list with the elements of the xml file
for (int i=0; i<list.getLength(); i++) {
Element element = (Element)list.item(i);
if (element.getNodeName().equals("field1")) {
field1 = element.getChildNodes().item(0).getNodeValue().toString();
} else if (element.getNodeName().equals("field2")) {
field2 = element.getChildNodes().item(0).getNodeValue().toString();
}
}
} catch (Exception e) {
System.out.println(e);
}
}
public void saveSampleProject(String field1Str, String field2Str) {
InputStream file = MyLoad_SaveSampleProject.class.getResourceAsStream("/main/resources/otherClasses/projects/SampleProject.xml");
try {
DocumentBuilderFactory DocBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder DocBuilder = DocBuilderFactory.newDocumentBuilder();
Document Doc = DocBuilder.parse(file);
NodeList list = Doc.getElementsByTagName("*"); //create a list with the elements of the xml file
for (int i=0; i<list.getLength(); i++) {
Node thisAttribute = list.item(i);
if (thisAttribute.getNodeName().equals("field1")) {
thisAttribute.setTextContent(field1Str);
} else if (thisAttribute.getNodeName().equals("field2")) {
thisAttribute.setTextContent(field2Str);
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(Doc);
StreamResult result = new StreamResult(new File("src/main/resources/otherClasses/projects/SampleProject.xml"));
transformer.transform(source, result);
} catch (ParserConfigurationException pce) {
pce.printStackTrace();
} catch (TransformerException tfe) {
tfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (SAXException sae) {
sae.printStackTrace();
}
}
public String returnField1() {
return field1;
}
public String returnField2() {
return field2;
}
}
And this is my default XML file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><Strings>
<field1>string1</field1>
<field2>string2</field2>
</Strings>
When the save button is pressed I am using the saveSampleProject method. When the load button is pressed I am using the loadSampleProject method and then I am getting the field values with the returnField1 and returnField2 methods.
I have no idea of what could be wrong with what I'm doing. I would appreciate any suggestions.
Most probably that calling method getResourceAsStream() leads to resource caching. Since you are using File() in save method try to get InputStream on data load using File object, and not as resource.
My xml String is
Got message from Queue ==> <?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003
/05/soap-envelope"><soapenv:Body><ns1:PostPublicationResponse xmlns:ns1="http://www.openoandm.org/xml/ISBM/"><ns1:Messag
eID>urn:uuid:7d361fb0-bc54-48bd-bbd1-6e34960ef3f8</ns1:MessageID><ns1:MessageContent><MessageContent xmlns="http://www.o
penoandm.org/xml/ISBM/"><hi>k786</hi></MessageContent></ns1:MessageContent></ns1:PostPublicationResponse></soapenv:Body>
</soapenv:Envelope>
Now i have writtent a function that is trying to get Content of element MessageContent i.e <hi>k786</hi> but i am getting null value always.
My function to parse above xml is:
private String parseQueueMessage(String message)
throws ParserConfigurationException, SAXException, IOException,
XPathExpressionException {
String resultMsg = "";
DocumentBuilderFactory domFactory = DocumentBuilderFactory
.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new java.io.StringReader(
message)));
XPath xpath = XPathFactory.newInstance().newXPath();
// XPath Query for showing all nodes value
xpath.setNamespaceContext(new NamespaceContext() {
#SuppressWarnings("rawtypes")
#Override
public Iterator getPrefixes(String arg0) {
return null;
}
#Override
public String getPrefix(String arg0) {
return null;
}
#Override
public String getNamespaceURI(String arg0) {
if("xmlns:ns1".equals(arg0)) {
return "http://www.openoandm.org/xml/ISBM/";
}
return null;
}
});
XPathExpression expr = xpath.compile("//xmlns:ns1:MessageContent");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println("The message obtained after parsing : "
+ nodes.item(i).getNodeValue());
resultMsg = nodes.item(i).getNodeValue();
}
return resultMsg;
}
What i have done wrong in here?
Thanks in advance
You need to define the name space URI first before selecting from XPATH. For example, first define the namespace URI as follows on the root;
element.setAttribute("xmlns:ns1", "http://www.openoandm.org/xml/ISBM/");
xpath.compile("//ns1:MessageContent");
//Try something like ...
XmlDocument doc = new XmlDocument();
doc.LoadXml("urn:uuid:7d361fb0-bc54-48bd-bbd1-6e34960ef3f8k786
");
XmlElement elem = (XmlElement) doc.DocumentElement.FirstChild;
Console.Write("{0}:{1} = {2}", elem.Prefix, elem.LocalName, elem.InnerText);
Console.WriteLine("\t namespaceURI=" + elem.NamespaceURI);
this is my XML file :
<sitemesh>
<mapping path="/editor/tempPage/**" exclude="true"/>
<mapping decorator="/WEB-INF/views/decorators/detailstheme.jsp"
path="/*" exclude="false" />
</sitemesh>
I want list of mapping node with their attribute values.
this should be done using Xpath.
my xpath expression is :
expr = xpath.compile("/sitemesh/mapping");
but i am getting null in nodelist.
this is my code:
Map<String,String> map=new HashMap<String, String>();
// reading xml file
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
Document doc = null;
XPathExpression expr = null;
try {
builder = factory.newDocumentBuilder();
// creating input stream
doc = builder.parse(file);
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
expr = xpath.compile("//mapping");
} catch (Exception e) {
LOG.error("some exception message", e);
}
//------------------------------------------------------------------------
NodeList attributeElements = null;
try {
attributeElements =(NodeList)expr.evaluate(doc, XPathConstants.NODE);
} catch (XPathExpressionException e) {
LOG.error("some exception message", e);
}
System.out.println("lenght:"+attributeElements.getLength());
for (int i = 0; i < attributeElements.getLength(); i++) {
Node node=attributeElements.item(i);
System.out.println("node:"+node.getNodeValue());
NamedNodeMap attrs = node.getAttributes();
for(i = 0 ; i<attrs.getLength() ; i++) {
Attr attribute = (Attr)attrs.item(i);
System.out.println("Node Attributes : " + attribute.getName()+" = "+attribute.getValue());
}
}
//-------------------------------------------------------------------------
// writing xml file
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer;
try {
transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(file);// creating output
// stream
transformer.transform(source, result);
} catch (Exception e) {
LOG.error("some exception message", e);
}
return map;
i am getting null for attributeElements
i want to show values of path,decorator and exclude on JSP page.But i am unable to get list of node through xpath expression.
I want solution for reading mapping node element in Xpath.
[edit] /sitemesh/mapping also works .
The issue here is that you evaluating the express for XPathConstants.NODE while the nodeList maps to XPathConstants.NODESET. please refer below link.
http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/xpath/XPathConstants.html#NODESET
Added sample code for illustration purpose only:
public void testXpathExpr(){
String testXML = "<sitemesh><mapping path=\"/editor/tempPage/**\" exclude=\"true\"/><mapping decorator=\"/WEB-INF/views/decorators/detailstheme.jsp\" path=\"/*\" exclude=\"false\" /></sitemesh>";
NodeList nodeList = getNodeList(testXML);
}
private NodeList getNodeList(String xml) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = docFactory.newDocumentBuilder();
document = builder.parse(new ByteArrayInputStream( xml.getBytes() ) );
XPathExpression exprPath = xpath.compile(xpathExpr);
NodeList nodeList = (NodeList) exprPath.evaluate(document, XPathConstants.NODESET);;
return nodeList;
}
Hope this helps!
Your xpath works perfectly for me. Below is the sample code:
public class Parser {
public static void main(String[] args) throws Exception, Exception {
final DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.parse("src/sitemesh.xml");
final XPathFactory xPathfactory = XPathFactory.newInstance();
final XPath xpath = xPathfactory.newXPath();
final XPathExpression expr = xpath.compile("/sitemesh/mapping");
Object node = expr.evaluate(doc, XPathConstants.NODE);
System.out.println(node);
}
}
sitemesh.xml contains your sample input.