Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
The moose likes XML and Related Technologies and the fly likes Java XHTML DOM: Exception in getElementById with XPath Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Engineering » XML and Related Technologies
Bookmark "Java XHTML DOM: Exception in getElementById with XPath" Watch "Java XHTML DOM: Exception in getElementById with XPath" New topic
Author

Java XHTML DOM: Exception in getElementById with XPath

Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
I have an XHTML file and I have to add an element at the specific location after the div tag where id="id12". I'm using getElementById for this but as it was returning 'null' so I used XPath to locate the element and then indicated to the DOM to treat it as an attribute type of ID but still it is returning 'null'. However there are more requirements to match source and desired file but presently I'm just trying to add 'calculate.js' Javascript at the desired location. Please help me out in this matter. Thanks!

Part of Source XML:


Part of desired XHTML:



Part of my Java Code:



It returns output in console i.e. print value for found as -> [div:null]
I cannot modify the source file because I'm not allowed to do so. If there are any changes required regarding namespace then those have to be done through Java Program only.
Thanking you!
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

So your code found an Element, and you know what the toString() value of that Element is. Apparently that doesn't agree with what you expected to see, although you haven't told us what that was. But why are you concerned with what toString() returns? You have the Element, carry on and use it.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:So your code found an Element, and you know what the toString() value of that Element is. Apparently that doesn't agree with what you expected to see, although you haven't told us what that was. But why are you concerned with what toString() returns? You have the Element, carry on and use it.

Thanks for the reply. Can you please clarify it? I searched here and there I found that this problem can be caused due to default namespace in my source file, so I added a prefix in that and then modified my XPath. I'm pasting my entire java code here please have a look in that and tell me whats wrong with that.



It still returns the same.>
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:So your code found an Element, and you know what the toString() value of that Element is. Apparently that doesn't agree with what you expected to see, although you haven't told us what that was. But why are you concerned with what toString() returns? You have the Element, carry on and use it.


Should I remove Element found and carry on?
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

I have no idea what your last two posts mean. And in particular I don't understand what this "problem" is. You have code which was looking for a certain Element, and it found an Element. So what's the problem? Do you think it found the wrong Element? Because you haven't produced anything which suggests that.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:I have no idea what your last two posts mean. And in particular I don't understand what this "problem" is. You have code which was looking for a certain Element, and it found an Element. So what's the problem? Do you think it found the wrong Element? Because you haven't produced anything which suggests that.


Actually I have to add an element at particular position, so I'm using getElementById where id="id12" but the problem is its returning null value.
For this program I'm getting the output [div:null].
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

You mean the toString() value of that Element contains the string "null". I'm still not seeing why that is a problem. In fact I'm not seeing why the toString() value of the Element has anything to do with your requirements at all.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:You mean the toString() value of that Element contains the string "null". I'm still not seeing why that is a problem. In fact I'm not seeing why the toString() value of the Element has anything to do with your requirements at all.


Here-
Element found = doc.getElementById("id12");
System.out.println(found);

The value of 'found' is null while it should match with the div tag where id="id12". So when I try to add a child node with getElementById("id12"), then it remains as it is because its unable to find the matching tag due to null value.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Rahul Divedi wrote:The value of 'found' is null.


But previously you said

For this program I'm getting the output [div:null].


Yes, this does contain the four letters n, u, l, l, but it isn't null. It's a string which happens to contain those four letters. So which is it? Not that it really matters -- the toString() value of an Element is useless information anyway, as I have been trying to explain. So forget about it and start looking for real problems.
William Brogden
Author and all-around good cowpoke
Rancher

Joined: Mar 22, 2000
Posts: 12761
    
    5
Everybody working with XML DOMs should be familiar with the lovely table in the org.w3c.dom.Node JavaDocs.

From this table you can see that most Node types - such as Element - have a null nodeValue - thats what produces "null" when you do a toString() operation on an Element.

Bill
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
@Rahul Divedi
I refer only to the first post. From the code fragment, I can only conclude that the logic within the code is quite disjoint: one block does not follow quite naturally the other... The use of dom is quite lost...

First of all, I suppose you set up the doc with a namespace aware parser? If not, I would suggest you doing so because even it would save some effort in this case using namespace unaware parser, but it risks to learn wrong concepts at this stage hard to unlearn later on. In any case, I suppose it is established via a namespace aware dom parser hereon.

Using xpath is an approach that I slightly prefer for its more precise searching power, but you need to aware how namespace influence the coding. So, first I would suggest a pure dom api (up to level 3 support) then the xpath approach with a more precise search (meaning the resulting getLength() of the NodeList of both approaches is shorter for xpath than for getElementsByTagNameNS()).

[1] Dom's document class supports getElementsByTagName() and getElementsByTagNameNS() according to the presence of namespace or not. They basically flattens out the dom hierachy structure. The search however is not that precise and needs more coding to locate the element(s) precisely. This is how.

[2] To use xpath, you need to code a namespace handler. This is the bare minimum.

Since there no assurance id being in the sense of xml type ID, so the uniqueness cannot be given for granted.

So you see how one way or another of how to identify the targetted element. From thereon, what you want to do with it, I do not see a consistent discourse, hence, I cannot help just not to waste time of both sides.
>
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
g tsuji wrote:@Rahul Divedi
I refer only to the first post. From the code fragment, I can only conclude that the logic within the code is quite disjoint: one block does not follow quite naturally the other... The use of dom is quite lost...


Thanks a lot for the reply. I'm going to try in the way you have told.
I have set: factory.setNamespaceAware(true); in my code.
PS:Sorry for the late reply i.e. just because of some personal reasons, I couldn't access.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
g tsuji wrote:



Here in the method evaluate(String, Object) apart from 'sxp' what arguement I need to add? Whatever argument I add there then it says change the type of 'nodes' to String. Can you please help..
Thanks!
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
Thanks for the response. Sorry, that line should be read like this (and that you'd been aware, and that I just typing the code in real time without testing).

... and the sxp is in the line#1 of that block, I just isolated it for clarity.

Also I now noticed you've also something of namespace handling along the same line in your latter posts..., so you can keep your prefix as you like. However, as the xhtml is not shown in its completeness, I cannot ascertain whether the xpath expression is appropriate or not. Mine has factored that uncertainty for probably a bit of performance.

Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
g tsuji wrote:T
NodeList nodes=(NodeList)xPath.evaluate(sxp,doc,XPathConstants.NODESET);
[/code]
... and the sxp is in the line#1 of that block, I just isolated it for clarity.
[code]
String sxp="/xhtml:html/xhtml:body//xhtml:div[@id='id12']";
[/code]


Thanks a lot for the reply. I'll try in the way you have mentioned and will get back to you. Thanks again for the help.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
g tsuji wrote:T
NodeList nodes=(NodeList)xPath.evaluate(sxp,doc,XPathConstants.NODESET);
[/code]
... and the sxp is in the line#1 of that block, I just isolated it for clarity.
[code]
String sxp="/xhtml:html/xhtml:body//xhtml:div[@id='id12']";
[/code]

I tried with this solution but I'm getting the following error in the same line-

javax.xml.xpath.XPathExpressionException
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.evaluate(Unknown Source)
at org.dom.Dom.main(Dom.java:77)
Caused by: javax.xml.transform.TransformerException: misquoted literal... expected single quote!
at com.sun.org.apache.xpath.internal.compiler.XPathParser.error(Unknown Source)
at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Unknown Source)
at com.sun.org.apache.xpath.internal.compiler.Lexer.tokenize(Unknown Source)
at com.sun.org.apache.xpath.internal.compiler.XPathParser.initXPath(Unknown Source)
at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source)
at com.sun.org.apache.xpath.internal.XPath.<init>(Unknown Source)
at com.sun.org.apache.xpath.internal.jaxp.XPathImpl.eval(Unknown Source)
... 2 more


Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
g tsuji wrote:Thanks for the response. Sorry, that line should be read like this (and that you'd been aware, and that I just typing the code in real time without testing



Yes I understand that you haven't done the real time testing thats why there can be some minor errors but I really appreciate your help. Its really a great help for me indeed. I'm posting my modfied java code after you suggestions. Please have a look and I have corrected my XPath. Should I paste my XHTML so that you could check out the XPath. Thanks a lot again for your help. Meanwhile I'm trying to debug that error.

>
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Yes, your XPath is wrong. It's missing a closing quote after the attribute value. But I'm surprised you didn't get an exception thrown when you ran that code?
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:Yes, your XPath is wrong. It's missing a closing quote after the attribute value. But I'm surprised you didn't get an exception thrown when you ran that code?

Thanks a lot again for the help, I have fixed that. I have tried to print the value of 'found' and its printing '[div:null]'. So is it because of wrong XPath?
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:Yes, your XPath is wrong. It's missing a closing quote after the attribute value. But I'm surprised you didn't get an exception thrown when you ran that code?


Please find my short but complete XHTML here, so is my XPath correct?



Thanking you!

Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Rahul Divedi wrote:I have tried to print the value of 'found' and its printing '[div:null]'. So is it because of wrong XPath?


No, it's more likely to be because of the correct XPath. That string suggests to me that your XPath has found a <div> element, which is what you asked it to look for. And of course the "value" of that <div> element, because Element objects always have null for their value. I believe William Brogden already directed you to the API documentation which tells you that the "value" is null. Which of course is irrelevant because you aren't interested in the "value" of the element anyway.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Paul Clapham wrote:
Rahul Divedi wrote:I have tried to print the value of 'found' and its printing '[div:null]'. So is it because of wrong XPath?


No, it's more likely to be because of the correct XPath. That string suggests to me that your XPath has found a <div> element, which is what you asked it to look for. And of course the "value" of that <div> element, because Element objects always have null for their value. I believe William Brogden already directed you to the API documentation which tells you that the "value" is null. Which of course is irrelevant because you aren't interested in the "value" of the element anyway.

Thanks for the reply. Actually I have to append tag called 'script' after the div tag where id="id12", which I have located through XPath. Now I'm using the value of 'found' to append the child in the following manner-
found.append(script2) but in the generated XHTML file it is not appending anything. So is this way -> Element found = doc.getElementById("id12"); correct?

This is the method which I have tried for adding a tag called 'script' after the div tag where id="id12"-

Thanking you!>
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
[1] You have to establish solidly the correctness of the xhtml first. I have looked at it and then no, it can't be correct! already at that level and any work on it is vain and misleading.

[1.1] The xhtml lack one closing </div> and I don't know why it is not noted whenever running any code to establish the doc, Document object.

[1.2] Then this line in the xhtml
<div id="taquestion0b12" class="block" style="display:block">1><span style="color: #000000;"> SQL Stands for ?</span>
</div>

This can't be correct. The closing angle bracket after 1, what is it? Either take it out or it must appear in the xhtml and &gt; or similarly encoded.

[2] Then the namespace context handling.
[2.1] If you choose to use prefix "x", it is just fine, but it must be consistently coded in the handling.

[2.2] What is again the angle bracket in the Iterator??? Take it out!


And then I have seen plenty of serious errors in the coding logic itself. I will come back to that part.
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
[3] Now to clear up your obsessed method getElementById(). This is an extension used in js/javascript/vbs or any other mainly scripting (client or not necessarily used client-side). In java jdk proper, you are not allowed to use as freely as that in the scripting language. It is supported long time ago already of dom level 2, but, there is a pre-condition for its application: namely, the document must be validated beforehand. If not, there is no way to know id means ID in the specific sense of xml data typing (defined either in dtd or xsd or whatever schema). For a non-validating parser, the getElementById() always return precisely null (even apparently there is an id attribute and there is an id="id12" to be precise).
Element found = doc.getElementById("id12");

If you System.out.println(found), it is always null (not [div: null] or whatever else).
So, you are not going to use it if you do not validate the document. Besides, the use of XPath or getElementsByTagNameNS() and the story that I was trying to tell is not for the diversion. It is for the locating the target element div with id="id12"!!!

[4]

NodeList nodes=(NodeList)xPath.evaluate(sxp,doc,XPathConstants.NODESET);
for (int i=0; i<nodes.getLength(); i++) {
Element elem=(Element)nodes.item(i);
//each one is the searched div element with id attribute id12
elem.setIdAttribute("id", true);
Element found = doc.getElementById("id12");
// System.out.println("ELement found is:"+found);
Element script2 = doc.createElement("script");
script2.setAttribute("src", "cal.js");
script2.setAttribute("type","text/javascript");
script2.setAttribute("xml:space","preserve");
found.appendChild(script2);
}

Now this is a bit "ridiculous", is it not? The element "found" is precisely what is found and stored in the nodes (NodeList). If you want to know the element found, it is this.

period. There is no further work to location those elements div with @id="id12".

[4.1] Then the adding of child to it. You again have to notice script in xhtml is again an element within the namespace x (or xhtml). You have to use createElementNS() method. This is how it would look like.

[4.2] Same problem for your getElementsByTagName("head") section. You again have to use getElementsByNameNS() as shown in my previous posts. Again, the createElement() the same error, you've to use createElementNS() variant.

For the moment, that's what I can help before getting really nervous.

PS This forum seems to have some problem in rendering hostil to xml message. The note in [1.2] may be due to the artifact in posting!>
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
(my own) Furthermore, what is setIdAttribute() method? never heard of it.

Sorry, I take back my comment on setIdAttribute(). My bad. But it is still misplaced with ambiguous meaning there. And I take it out.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
If updation is an easier task then if <script type="text/javascript" src="libot_drag.js"></script> replaced with <script type="text/javascript" src="cal.js"></script> ; will also do the job for me. Thanking you.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
g tsuji wrote:You have to establish solidly the correctness of the xhtml first. I have looked at it and then no, it can't be correct! already at that level and any work on it is vain and misleading.

I have corrected the XHTML input file. Please find it here-


My Java Code is-



This code is giving no error and generating the output file but the javascript is not getting appended after the tag where id="id12". Please check it out if there is furthermore amendment required. Thanking you. I'm really grateful to you for your kind help.>
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
[1.1.1] Adding one more closing div tag.

[4.2.1]
[4.2] Same problem for your getElementsByTagName("head") section. You again have to use getElementsByNameNS() as shown in my previous posts. Again, the createElement() the same error, you've to use createElementNS() variant.

Meaning...
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Thanks for the reply. I corrected the problems and ran the program again. It is adding the cal.js Javascript now but not at the right place (adding just before two div tags in the end). So is it happening due to wrong XPath? Please see this is the output which I'm getting-

Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
I just noticed that it is adding to that <div> tag only but not just after the opening rather just before the corresponding closing </div> tag.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
I wanted to ask you one thing that as I need to keep only one Javascript cal.js after that div tag and have to remove other two common.js and ligot.js, so will it be better or easier to modify the src of any of them and then to remove the spare one or this approach of adding cal.js and then removing other two is better? Thanks a lot for your help, I'm really grateful to you.
g tsuji
Ranch Hand

Joined: Jan 18, 2011
Posts: 499
    
    3
[5]
I just noticed that it is adding to that <div> tag only but not just after the opening rather just before the corresponding closing </div> tag.

That's because you use appendChild(). If you want to insert the script tag at the top, you reference to the first child (which is probably a text node or an element node) and use insertBefore() method to do that. That is easier. If you want to insert it just before the first element node, you have more code to do. I will show the simpler way of using getFirstChild() method in the recap below.

[6]
...that as I need to keep only one Javascript cal.js after that div tag and have to remove other two common.js and ligot.js, so will it be better or easier to modify the src of any of them and then to remove the spare one or this approach of adding cal.js and then removing other two is better?

You can again use removeChild() to remove all (or a subset of) the script tag(s) before inserting the script tag you created. There are often many ways to do the same thing. I would not bother that kind of slight difference in performance.

[7] Recap. Before listing how it would look, I would suggest you this time spare the loop looping the elements with id="id12". As it is probably only one, and if there are more, you won't want to do the same thing for everyone of them: that would be functionally wrong. So, I would suggest you isolate the item(0) and do thing on it only. If there are more than one node in the returned NodeList, you have to seriously ask yourself whether id is an id (doing validating beforehand) or decide how you would handle that.

This is the look recapturing all you need starting from block after the xpath block.

That's all. I hope my intervention comes to an end. With all the key action names, you can read the api documentation with more focus. This you've to do yourself. Nobody can do better than the documentation once you get over the basic and have seen the methods in action.
Rahul Divedi
Ranch Hand

Joined: Dec 11, 2011
Posts: 40
Thanks a lot all your valuable help. I really appreciate and really grateful to you for giving your precious time. I'll implement all your suggestions and soultions. :)
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Java XHTML DOM: Exception in getElementById with XPath
 
Similar Threads
JSPF file can not be included in JSP file and gives error
how to get input from javascript and pass to servlet
JavaScript troubles
[solved] passing 3 times by default through action using struts 2
HTML to HTML conversion using Java