2

I have the following table data to traverse in my HTML:

<table id="publicationTable" cellpadding="2" cellspacing="0">
<tr>
<td vAlign="top"><IMG SRC="/images/icons/general/spacer.gif" width="20" height="1"></td>
<td class="SmallColHeading">Published     </td>
<td class="ColRow">Publisher, place and date of publication</td>
</tr>
<tr>
<td vAlign="top"><IMG SRC="/images/icons/general/spacer.gif" width="20" height="1"></td>
<td class="SmallColHeading">
Format     </td>
<td class="ColRow">
vii, 201 pages ; 23 cm.     </td>
</tr>

I want to output the text "vii, 201 pages ; 23. cm." with document.evaluate but I am missing something. The thing is that the selector should be td with class attribute value "SmallColHeading" and that has (contains) a text node/value of Format.

var Pagination = document.evaluate("//td[contains(., 'Format')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );
var Pagination2 = Pagination.nextSibling.innerHTML;
if (Pagination.singleNodeValue) {
                var Pages = Pagination.singleNodeValue.textContent;
            }
alert(Pagination2);
alert(Pages);

I'm trying various combinations specially after nextSibling like removing innerHTML (I'm getting undefined) or replacing it with textContent (I'm getting Cannot read property 'textContent'). I'm struggling with traversing nextSibling through javascript on this HTML since tr does not even have an id value and this all what we have we have in the system. Thanks in advance!

schnydszch
  • 435
  • 5
  • 19
  • 1
    Do you specifically have to use XPath for this? Would [`.getElementsByClassName()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName) not suffice? – Obsidian Age Apr 30 '19 at 04:08
  • If .getElementsByClassName(), I'm fine with it for as long as I'm able to get the text value aforementioned. Thanks and cheers! – schnydszch Apr 30 '19 at 04:42

2 Answers2

2

I was able to achieve the result through the following codes:

 var Pages = document.evaluate("//td[contains(., 'Format')]/following-sibling::td", 
 document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null );
 if (Pages.singleNodeValue) {
                var pages = Pages.singleNodeValue.textContent;
            }

I should just have traversed after this: "//td[contains(., 'Format')]/" by adding "following-sibling::td" instead of adding a variable like this: "var Pagination2 = Pagination.nextSibling.innerHTML;" This post How to select following sibling/xml tag using xpath gave me hint as well as the initial links I looked into: Javascript .querySelector find <div> by innerTEXT and this: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_using_XPath_in_JavaScript

schnydszch
  • 435
  • 5
  • 19
0

There's no need for an XPath; this can be achieved rather simply with .getElementsByClassName() and .nextElementSibling:

var pagination = document.getElementsByClassName('SmallColHeading')[0];
var pagination2 = pagination.nextElementSibling;
console.log(pagination2.innerHTML.trim());
<table>
<tr>
  <td vAlign="top">
    <IMG SRC="/images/icons/general/spacer.gif" width="20" height="1" />
  </td>
  <td class="SmallColHeading">
    Format
  </td>
  <td class="ColRow">
    vii, 201 pages ; 23 cm.
  </td>
</tr>
</table>

.trim() can be used to get rid of any additional whitespace.

Note that <IMG> will need a self-closing tag, and that you need an outer <table> element. Without the containing <table>, the table contents will get added directly to <body>, and this the selector will be invalid.

Obsidian Age
  • 41,205
  • 10
  • 48
  • 71
  • Hi! Sorry for not explicitly stating in my question, I added this part: The thing is that the selector should be td with class attribute value "SmallColHeading" and that has (contains) a text node/value of Format. Because I'm not sure with the document structure but I'm pretty sure that it has this: Format vii, 201 pages ; 23 cm. – schnydszch Apr 30 '19 at 07:16