# Custom Keyword: get contents of HTML elements as a list of strings

**URL:** <https://forum.katalon.com/t/custom-keyword-get-contents-of-html-elements-as-a-list-of-strings/11137>\
**Category:** Web Testing\
**Tags:** tips-tricks, katalon-studio\
**Created:** [May 24, 2018, 7:50am UTC](https://forum.katalon.com/t/custom-keyword-get-contents-of-html-elements-as-a-list-of-strings/11137 "2018-05-24T07:50:26Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![kazurayam](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/kazurayam/32/333_2.png) [@kazurayam](https://forum.katalon.com/u/kazurayam)\
**Post date:** [May 24, 2018, 7:50am UTC](https://forum.katalon.com/t/custom-keyword-get-contents-of-html-elements-as-a-list-of-strings/11137/1 "2018-05-24T07:50:26Z")

</div>

**# Problem to solve**

Supposing the target web page has a list of element.

I want to verify the displayed contents against other list of strings list like this:

```auto
def expectedContents = [
    "Tokyo CURA Healthcare Center",
    "Hongkong CURA Healthcare Center",
    "Seoul CURA Healthcare Center" ]

```

However, in the built-in keywords of Katalon Studio, there is none which returns the contents of HTML elements as List.

**# My Solution**

I have developed a class [com.kazurayam.ksbackyard.FindElementsByXPath](https://github.com/kazurayam/KatalonDiscussion6967/blob/master/Keywords/com/kazurayam/ksbackyard/FindElementsByXPath.groovy "Link: https://github.com/kazurayam/KatalonDiscussion6967/blob/master/Keywords/com/kazurayam/ksbackyard/FindElementsByXPath.groovy") . This class provides 2 custom keywords.

- List getElementContentsAsList(String xpath4elements)

- List getElementAttributesAsList(String xpath4elements, String attributeName)

A sample Test Case looks like this:

```auto
def expectedContents = [ "Tokyo CURA Healthcare Center",
	"Hongkong CURA Healthcare Center",
	"Seoul CURA Healthcare Center" ]List<String> cs = CustomKeywords.'com.kazurayam.ksbackyard.FindElementsByXPath.getElementContentsAsList'('//select[@name="facility"]/option')
for (int i = 0; i < cs.size(); i++) {
    WebUI.verifyEqual(cs[i], expectedContents[i])
}

```

```auto
def expectedValues = [
    "Tokyo",
    "Hongkong",
    "Seoul" ]
List<String> vs = CustomKeywords.'com.kazurayam.ksbackyard.FindElementsByXPath.getAttributeValuesAsList'('//select[@name="facility"]/option', 'value')
for (int i = 0; i < vs.size(); i++) {
    WebUI.verifyEqual(vs[i], expectedValues[i])
}

```

**# My implementation**

See the following GitHub repository:

> **[GitHub - kazurayam/KatalonDiscussion6967: Custom Katalon Keyword:...](https://github.com/kazurayam/KatalonDiscussion6967)**
>
> Custom Katalon Keyword: FindElementsByXpath.getElementContentAsList(String xpath4elements)

[6967\_testbed.png](https://s3.amazonaws.com/katalon-forum/editor/pa/29khpharpjtz.png)

---

<div class="post-metadata">

**Author:** ![kazurayam](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/kazurayam/32/333_2.png) [@kazurayam](https://forum.katalon.com/u/kazurayam)\
**Post date:** [January 18, 2019, 10:12am UTC](https://forum.katalon.com/t/custom-keyword-get-contents-of-html-elements-as-a-list-of-strings/11137/2 "2019-01-18T10:12:26Z")

</div>

I have found that we do not need a custom keyword. A built-in keyword `WebUI.findWebElements(TestObject)` is available. You can write this

```auto
import org.openqa.selenium.WebElement
import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.testobject.ConditionType

...
// grasp <tr> elements
List<WebElement> trElements = WebUI.findWebElements(
	new TestObject().addProperty("xpath", ConditionType.EQUALS, 
							"//div[@id='resultDiv']/table/tbody/tr"), 10)
println "trElements.size()=${trElements.size()}"

```

See

> [@Chrome: saving an xml file instead of displaying it](http://forum.katalon.com/t/chrome-saving-an-xml-file-instead-of-displaying-it/15677/21):
>
> I extended my demo project further. See [GitHub - kazurayam/SavingAnXmlFileRatherThanDisplayingIt: Visit a web page, where I identify a href to RSS document; send GET request for the document and save it into local file; do all in a Katalon Test case](https://github.com/kazurayam/SavingAnXmlFileRatherThanDisplayingIt/) The Application Under Test [Sample](https://kazurayam.github.io/SavingAnXmlFileRatherThanDisplayingIt/) now has 3 rows: Please note: The 1st row contains 1 link to XML. The 2nd row contains no link to XML. The 3rd row contains 2 links to XML files. I added a Test Case [TC3](https://github.com/kazurayam/SavingAnXmlFileRatherThanDisplayingIt/blob/master/Scripts/TC3/Script1546641047357.groovy). This test case scans the target HT…

for working example.

---

<div class="post-metadata">

**Author:** ![Mate\_Mrse](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/mate_mrse/32/345_2.png) [@Mate\_Mrse](https://forum.katalon.com/u/Mate_Mrse)\
**Post date:** [January 18, 2019, 11:41am UTC](https://forum.katalon.com/t/custom-keyword-get-contents-of-html-elements-as-a-list-of-strings/11137/3 "2019-01-18T11:41:07Z")

</div>

kazurayam, what would you say is the relation between test object and web element in this case?

Is it just a one-to-one translation between Selenium’s web elements and Katalon’s test objects?

---

<div class="post-metadata">

**Author:** ![kazurayam](https://dub1.discourse-cdn.com/katalon/user_avatar/forum.katalon.com/kazurayam/32/333_2.png) [@kazurayam](https://forum.katalon.com/u/kazurayam)\
**Post date:** [January 18, 2019, 12:54pm UTC](https://forum.katalon.com/t/custom-keyword-get-contents-of-html-elements-as-a-list-of-strings/11137/4 "2019-01-18T12:54:43Z")

</div>

I have update my demo project:

- [https://github.com/kazurayam/SavingAnXmlFileRatherThanDisplayingIt/blob/master/Scripts/TC4/Script1547814309014.groovy](https://github.com/kazurayam/SavingAnXmlFileRatherThanDisplayingIt/blob/master/Scripts/TC4/Script1547814309014.groovy)

* * *

TC4:

```auto
// grasp <tr> elements : 1st way; using Katalon API with a TestObject constructed beforehand 
List<WebElement> trElements1 = WebUI.findWebElements(
	findTestObject("Page_Sample/div_resultDiv.table.tbody.tr"), 10)
println "trElements1.size()=${trElements1.size()}"

// grasp <tr> elements : 2nd way; using Katalon API with a TestObject constructed on the fly
List<WebElement> trElements2 = WebUI.findWebElements(
	new TestObject().addProperty("xpath", ConditionType.EQUALS,
							"//div[@id='resultDiv']/table/tbody/tr"), 10)
println "trElements2.size()=${trElements2.size()}"

// grasp <tr> elements : 3rd way; using WebDriver's native API
WebDriver driver = DriverFactory.getWebDriver()
List<WebElement> trElements3 = driver.findElements(By.xpath("//div[@id='resultDiv']/table/tbody/tr"))
println "trElements3.size()=${trElements3.size()}"

```

This code prints the following output:

```auto
...
trElements1.size()=3
...
trElements2.size()=3
...
trElements3.size()=3

```

In the above code, I showed 3 ways of grasping `<tr>` elements in a HTML. These 3 ways have just the same result.

* * *

Mate\_Mrse asked about

> the relation between test object and web element

I think this question is a bit misdirected. Katalon’s Test Object can be regarded equivalent to the `org.openqa.selenium.By` class. Both classes are the container of selector expression (XPath or CSS).  
They are not equivalent to `org.openqa.selenium.WebElement` class, which represents a \<node\> found in the target HTML.

A Test Object enables you to serialize a selector expression (XPath or CSS) into Object Repository. In other words, a Test Object externalizes selector expression out of a test case code by saving them into XML files. Externalized selectors will be easier to manage and reuse, than the case where selectors are left buried in test case scripts. That would be a reason why Test Object is prefered to By object. However I often prefer By object to Test object when I write a short one-off test case snippet because I know I would not reuse the selector at all.
