Get the computed style of a DOM element - java

After a layout is completed, I want to parse through the DOM tree and get the computed styles of each element. Is this possible.
The closest I could get is the below snippet, but it gives only uncomputed styles.
Element elm = (Element) _doc.getElementsByTagName("table").item(0);
Map props = _sharedContext.getCss().getCascadedPropertiesMap(elm);
Is it also possible to get which "Box" the element lies in.

You can access the computed style in the document with ITextRenderer.getRootBox().
This method return a tree of org.xhtmlrenderer.render.Box objects which you can scan to find your element.
You can get the box computed style with Box.getStyle() and you can get the element the box refers to with Box.getElement().

Related

Is it possible to find common xpath for this elements?

xpath of one element is: //div[#class=name-slider-header']//button//img[2]
xpath of another element is: //div[#class=name-slider-header']//button//img[1]
Actually I need to check attribute of element must contains "red" after element gets disabled
after clicking "n" times, so I am using element.getAttribute("src").contains("red");
element2.getAttribute("src").contains("red");
Is it possible to find common xpath for this elements?
Use the following xpath to identify the image elements where src value contains red
//div[#class='name-slider-header']//button//img[contains(#src, 'red')]
code:
imgElements = driver.findElements(By.xpath("//div[#class='name-slider-header']//button//img[contains(#src, 'red')]"));
The common XPath of these 2 elements is //div[#class=name-slider-header']//button//img. So, you can get a list of elements and then iterate over the list extracting the element attribute, as following:
elements = driver.findElements(By.xpath("//div[#class=name-slider-header']//button//img"));
for(WebElement element : elements){
if(element.getAttribute("src").contains("red")){
// do something
}
}

selenium webdriver xpath search by index

I am trying to identify a xpath of a textfield where the class name is "DeleteBackwardTextField" and Origin class is "UITextField". There are no label, name and text it. No other information to identify it.
There are 2 textfield with same above properties.
So my following xpath identifies two text fields.
By.xpath("//textfield[#class='DeleteBackwardTextField']")
How can I identify the xpath of 1 particular field. I assume index can be used. Can anybody provide a syntax for indexing.
Appreciate your help.
You can go with XPATH or CSS. The trick is to have a list of WebElements identified and then you can iterate over it.
List<WebElement> myList = driver.findElements(by.cssSelector(...); //or XPATH;
for (WebElement txtField : myList) {
// do what you need here, for each element at a time
}
Use this xpath.
(//textfield[#class='DeleteBackwardTextField'])[index]
EX: (//textfield[#class='DeleteBackwardTextField'])[1] -> first element when you have many elements matching //textfield[#class='DeleteBackwardTextField']
Note that this xpth - //textfield[#class='DeleteBackwardTextField'][2] has different meaning - it means second child of its parent.

Evaluate many elements with XPathExpression and NODESET

I parse a very large xml file (from jpylyzer, a jp2 properties extractor). This xml contains properties of many JP2 images, each one with the same elements, like :
//results/jpylyzer/fileInfo/fileName
//results/jpylyzer/properties/jp2HeaderBox/imageHeaderBox/height
//results/jpylyzer/properties/jp2HeaderBox/imageHeaderBox/width
//results/jpylyzer/properties/jp2HeaderBox/imageHeaderBox/bPCDepth
In order to reduce processing time, I'm using this method :
for (XPathExpression xPathExpression : listXPathExpression) {
nodeList = (NodeList) xPathExpression.evaluate(document, XPathConstants.NODESET);
//we use our list
}
It's very convenient and fast, but the number of elements must be as we expected for each property.
As some properties are unique to some images, some xpath values won't be found for some images.
nodeList is filled ONLY with found values, which is a problem : there's no way to match those values to other ones as lists don't have the same size depending on how many properties has been found.
Is there a way to fill "blank" when no value is found ?
What you want is not possible with a single XPath expression, not even with version 2.0. In such a case, you have to reach for the higher-level language you embed XPath in.
As I'm not familiar with Java very much, I cannot give you specific code, but I can explain what you have to do.
I assume an XML document similar to
<results>
<jpylyzer>
<fileInfo>
<fileName>Name of file</fileName>
</fileInfo>
<properties>
<jp2HeaderBox>
<imageHeaderBox>
<height>45</height>
<width>66</width>
<bPCDepth>386</bPCDepth>
</imageHeaderBox>
<imageHeaderBox>
<width>32</width>
</imageHeaderBox>
</jp2HeaderBox>
</properties>
</jpylyzer>
</results>
As a starting point, find an element that really is present in all XML documents, in all situations. For the sake of an example, let us assume imageHeaderBox is present everywhere, but its children height, width and bPCDepth are not necessarily there.
Find an XPath expression for the imageHeaderBox element:
/results/jpylyzer/properties/imageHeaderBox
evaluate the expression and save the result to a nodeList. Next, process this list further. This only works if XPath expressions can be applied to the individual items in a nodeList, but it seems you are optimistic about that:
I can iterate over nodelist. I guess i can evaluate too
Iterate over the nodeList (the result of the imageHeaderBox expression) and apply another path expression to each item.
XPath 2.0
In XPath 2.0, you can use an if/then statement that checks for the presence of a node. Assuming the imageHeaderBox element node as the context item:
if(height) then height else 'e.g. text saying there is no height'
XPath 1.0
With XPath 1.0, it's slightly more complicated:
concat(height, substring('e.g. text saying there is no height', 1 div not(height)))"
See Dimitre Novatchev's answer here for an explanation. The technique is known as the Becker method, probably introduced here.
Finally, the result list should look similar to
45
e.g. text saying there is no height

In Jsoup, is it possible get the Elements from a list of Elements without runs through it?

I'm new to Jsoup, but this appears to be a great tool. I'm trying to extract the robots metatag.
I have the following code:
Document doc = Jsoup.parse(htmlContent);
Elements metatags = doc.select("meta");
Element robots = metatags.attr("name", "robots"); // is getting the first element of the list
The last line is wrong.
I want to know if is necessary to run the list of elements to find the element that matches the attribute or there a way that extracts the element that matches the attribute from the Elements list.
Edit 1: I solved this changing to doc.select("meta[name=robots]").
Edit 2: In another words: I want to know how to get all elements in a Elements list that matches some atribute requisite.
Edit 3: I was precipitated doing this question because I had not seen the main documentation yet. Sorry.
It's possible to set the attribute and value you want to retrieve in the select() method to do a better filtering.
Change the select to: doc.select("meta[name=robots]"); and it will get all elements that has the meta tag and it have the name attribute equals robots.
Have you read the JSoup documentation? Here it is from the method you are using:
attr
public Elements attr(String attributeKey,
String attributeValue)
Set an attribute on all matched elements.
Parameters:
attributeKey - attribute key
attributeValue - attribute value
Returns:
this
It returns this. Which means it will return an Elements object. This can't be assigned to an Element object.
I also think you want to use Document.getElementsByTag(String), instead of select.

Get Text Content of xml element

So, i have some question about xml Documents in Java. Can i get all text(only text) content of some element and all descendant's elements of this element, without to iterate through all this elements and using Element.getText()? By another words, it must be some analogous function to JavaScript textContent. Or i must to iterate through all nodes?
You'll need to iterate and append.

Categories