Get same div level but different class name with jsoup - html

I would like to get data from html
<div class="xyz">
<div class="opq">
<div class="one">One</div></div>
<div class="rst">
<div class="vwu">
<div class="alpha">A</div></div></div>
<div class="opq">
<div class="one">Two</div>
<div class="rst">
<div class="vwu">
<div class="alpha">B</div></div></div>
<div class="rst">
<div class="vwu">
<div class="alpha">C</div></div></div>
<div class="opq">
<div class="one">Three</div></div>
<div class="rst">
<div class="vwu">
<div class="alpha">D</div></div></div>
</div>
</div>
How i can get the data in new format, where A is child of One, Two is parents of B and C, and so D is parents of D. When i try use loop for ( element) i just get all of component. I have trouble to get element between One - Two - Three. There only one element (A) between "One" dan "Two". Next, 2 element (B & C) between "One" and "Two". The Last one is only 1 element, D, after "Three".
And i will show like :
One :
> A
Two :
> B
> C
Three :
> D
I use eq(0) to access them, but the result show false output.
To do that i'm simply doing this:
Elements ht = dok.select("div.one");
Elements li = dok.select("div.alpha:eq(0)");
for(Element el : ht ){
System.out.println(el.ownText()+" : "+li.get(i).text());
i++;
}
But the result was:
One :
> A
Two :
> B
Three :
> C
based on the result, isn't like what i hope. That's it between "Two" and "Three" actually have 2 element, B and C. While the last "Three" it must have element of D. But in this result , the element D is can't display.
Thanks for any advice

Related

Jquery Find, Sort and then Append only specific 'N' numbers child element

I am finding child elements from the parent element and sorting them and then adding them on the parent element again:
$('#parentElement').find('.childElement').sort(function(a, b) {
var contentA = parseInt($(a).attr('data-name'));
var contentB = parseInt($(b).attr('data-name'));
return (contentA < contentB) ? 1 : (contentA > contentB) ? -1 : 0;
}).appendTo('#parentElement');
But I want to append only the first 5 sorted child elements on the parent element. I don't want to append all child elements. Any solution?
To get the first 5 sorted elements from that collection you can use .slice(). Also note that the code can be made more succinct by using data() to retrieve the attributes (as this will negate the need to manually call parseInt()) and also by combining the original selectors:
$('#parentElement .childElement').remove().sort((a, b) => {
var contentA = $(a).data('name');
var contentB = $(b).data('name');
return (contentA < contentB) ? 1 : (contentA > contentB) ? -1 : 0;
}).slice(0, 5).appendTo('#parentElement');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div id="parentElement">
<div class="childElement" data-name="1">1</div>
<div class="childElement" data-name="9">9</div>
<div class="childElement" data-name="4">4</div>
<div class="childElement" data-name="10">10</div>
<div class="childElement" data-name="3">3</div>
<div class="childElement" data-name="6">6</div>
<div class="childElement" data-name="5">5</div>
<div class="childElement" data-name="8">8</div>
<div class="childElement" data-name="2">2</div>
<div class="childElement" data-name="7">7</div>
</div>

XPath return value on sibling value multiple with conditions

This is how the HTML is structured; I am attempting to obtain the value of <div> if the sibling <p> is equal to type1
<div class="zsg-lg">
<div class="hdp-fact-ataglance">
<div class="media-bd">
<p>
type1
<div>
value
<div class="zsg-lg">
<div class="hdp-fact-ataglance">
<div class="media-bd">
<p>
type2
<div>
value2
Here's my XPath that's currently not working, I'm pretty confused on how to structure it.
div[contains(#class, "zsg-lg")]/div[contains(#class, "hdp-fact-ataglance")]/div[contains(#class, "media-bd") and [p == "Type"]]/div/text()
I would suggest this:
normalize-space(
//div[contains(#class, "zsg-lg")]
/div[contains(#class, "hdp-fact-ataglance")]
/div[
contains(#class, "media-bd")
and
normalize-space(p/text())="type1"
]
/div
/text()
)
looks like the syntax was a little off, this worked:
div[contains(#class, "zsg-lg")]/div[contains(#class, "hdp-fact-ataglance")]/div[contains(#class, 'media-bd') and p = 'type1']/div/text()

Cound divs inside div with Jsoup

I have a page where several status can be found. I would like to count all serviceStatus-OK and serviceStatus-DOWN divs on the page. Unfortunately I cannot modify the page, I need to verify all service is up and running. My idea is that, load the page, count all OK status. If 5 service has 5 OK, we are good. If there is any DOWN, we are not ok.
Any ideas?
Source code:
<span id="content">
<div class="status">
<div class="serviceName">
Some name <br />
http://blablaservice1
</div>
<div class="serviceStatus-OK">
OK
</div>
</div>
<div class="status">
<div class="serviceName">
Some other name <br />
http://blablaservice2
</div>
<div class="serviceStatus-DOWN">
DOWN
</div>
</div>
My code:
Elements services = doc.select("span#conent");
Element content = doc.getElementById("content");
Elements servicesOks = content.getElementsByTag("status");
int upCounter = 0;
int downCounter = 0;
for (Element y : servicesOks) {
if (y.hasClass("status-OK")) {
upCounter++;
}
}
for (Element y : servicesOks) {
if (y.hasAttr("status-DOWN")) {
downCounter++;
}
}
System.out.println("OK Systems: " + upCounter);
System.out.println("DOWN Systems: " + upCounter);
My output is:
OK Systems: 0
DOWN Systems: 0
You can find the number of okays and downs like this:
Document doc = Jsoup.parse(input);
Elements OK = doc.select(".serviceStatus-OK");
Elements down = doc.select(".serviceStatus-DOWN");
System.out.println("OK - " + OK.size());
System.out.println("DOWN - " + down.size());
Find all the elements with the names serviceStatus-OK and serviceStatus-DOWN, and then count the number of items of each kind (elemnts is just a list).

Bootstrap - How can I move a row's div into another row?

I'm learing bootstrap and I'm working with the Grid System since I'm working to a responsive website with lots of tables.
<div class="row">
<div class="col-md-1">A</div>
<div class="col-md-1">B</div>
<div class="col-md-1">C</div>
</div>
<div class="row">
<div class="col-md-1">D</div>
<div class="col-md-1">E</div>
<div class="col-md-1">F</div>
</div>
I will start with this bootstrap "table". I want to move a div of the first row into the second row. Example:
<div class="row">
<div class="col-md-1">A</div>
<div class="col-md-1">B</div>
</div>
<div class="row">
<div class="col-md-1">C</div>
<div class="col-md-1">D</div>
<div class="col-md-1">E</div>
<div class="col-md-1">F</div>
</div>
I think you are misunderstanding how Bootstrap works. Its grid does not work by "moving a row's div into another row". What happens is that the grid is based off of 12 columns per row. If you want 3 elements in 1 row, you would set each one with a class of col-xx-4 (xx is either lg, md, sm or xs), since 12/4 = 3. Each element takes up 4 of the 12 columns.
For your issue at hand - you can put all 6 elements in the same row and adjust the number of columns each one spans based on the screen size using lg, md, sm and xs. Below is an example that does what I believe you are trying to do my manually moving a row's div, but this way utilizes Bootstrap's grid system correctly.
<div class="container">
<div class="row">
<div class="col-sm-4 col-xs-6">
A
</div>
<div class="col-sm-4 col-xs-6">
B
</div>
<div class="col-sm-4 col-xs-6">
C
</div>
<div class="col-sm-4 col-xs-6">
D
</div>
<div class="col-sm-4 col-xs-6">
E
</div>
<div class="col-sm-4 col-xs-6">
F
</div>
</div>
</div>
Here is a Demo JSFiddle
You can slide the screen to make it bigger/smaller and see the 2 rows of 3 collapse to 3 rows of 2, and vice-versa.
If I got what you wanted to ask, the simplest way to do it is by:
1) Checking the browser's width.
2) Then, get the inner element you want to move.
3) Add it to where you want to take it.
4) And remove it from it was before.
The code HTML:
<div class="row" id="row1">
<div class="col-md-1">
A
</div>
<div class="col-md-1">
B
</div>
<div class="col-md-1" id="moveto">
</div>
</div>
<div class="row" id="row2">
<h4>--</h4>
<div class="col-md-1" id="movefrom">
C
</div>
<div class="col-md-1">
D
</div>
<div class="col-md-1">
E
</div>
<div class="col-md-1">
F
</div>
</div>
The JS code:
$(document).ready(function() {
var x = document.getElementById("movefrom").innerHTML // Get the inner HTML (C in this case)
if (window.innerWidth <= 768) { // Check the browser's width
document.getElementById("moveto").innerHTML = x; // Move the element to where you want (moveto id)
document.getElementById("movefrom").innerHTML = "" // Replace the element by an empty string.
}
});
This was the most simple way I found to make it work.
Any feedback is great!
Good luck
It is my hobby to answer too late.
Do this if you want it to respond to resize and work both ways:
window.addEventListener("resize", function(event) {
//grab what to replace
var x = document.getElementById("social")
.innerHTML;
//for when going to smaller screen
if (window.innerWidth <= 560 && !x == "") {
document.getElementById("social-mobile")
.innerHTML = x;
document.getElementById("social")
.innerHTML = "";
}
var y = document.getElementById("social")
.innerHTML;
// if we are at bigger screen and node is "", then put it back
if (window.innerWidth >= 560 && y == "") {
document.getElementById("social")
.innerHTML = document.getElementById("social-mobile")
.innerHTML;
document.getElementById("social-mobile")
.innerHTML = "";
}
});
😎
Well, I have this simple jQuery function..
(function($){
$.fn.moveTo = function(selector){
return this.each(function(){
var cl = $(this).clone();
$(cl).prependTo(selector);
$(this).remove();
});
};
});
usage $('.element').moveTo('.element2');, you can also change it to appendTo, or send a parameter to change it.

How to access div element text based on adjacent text

I have the following HTML code and am trying to access "QA1234", which is the value of the Serial Number. Can you let me know how I can access this text?
<div class="dataField">
<div class="dataName">
<span id="langSerialNumber">Serial Number</span>
</div>
<div class="dataValue">QA1234</div>
</div>
<div class="dataField">
<div class="dataName">
<span id="langHardwareRevision">Hardware Revision</span>
</div>
<div class="dataValue">05</div>
</div>
<div class="dataField">
<div class="dataName">
<span id="langManufactureDate">Manufacture Date</span>
</div>
<div class="dataValue">03/03/2011</div>
</div>
I assume you are trying to get the "QA1234" text in terms of being the "Serial Number". If that is correct, you basically need to:
Locate the "dataField" div that includes the serial number span.
Get the "dataValue" within that div.
One way is to get all the "dataField" divs and find the one that includes the span:
parent = browser.divs(class: 'dataField').find { |div| div.span(id: 'langSerialNumber').exists? }
p parent.div(class: 'dataValue').text
#=> "QA1234"
parent = browser.divs(class: 'dataField').find { |div| div.span(id: 'langManufactureDate').exists? }
p parent.div(class: 'dataValue').text
#=> "03/03/2011"
Another option is to find the serial number span and then traverse up to the parent "dataField" div:
parent = browser.span(id: 'langSerialNumber').parent.parent
p parent.div(class: 'dataValue').text
#=> "QA1234"
parent = browser.span(id: 'langManufactureDate').parent.parent
p parent.div(class: 'dataValue').text
#=> "03/03/2011"
I find the first approach to be more robust to changes since it is more flexible to how the serial number is nested within the "dataField" div. However, for pages with a lot of fields, it may be less performant.