Library version: | 3.1.1 |
---|---|
Library scope: | global |
Named arguments: | supported |
Robot Framework test library for verifying and modifying XML documents.
As the name implies, XML is a test library for verifying contents of XML files. In practice it is a pretty thin wrapper on top of Python's ElementTree XML API.
The library has the following main usages:
XML can be parsed into an element structure using Parse XML keyword. It accepts both paths to XML files and strings that contain XML. The keyword returns the root element of the structure, which then contains other elements as its children and their children. Possible comments and processing instructions in the source XML are removed.
XML is not validated during parsing even if has a schema defined. How possible doctype elements are handled otherwise depends on the used XML module and on the platform. The standard ElementTree strips doctypes altogether but when using lxml they are preserved when XML is saved.
The element structure returned by Parse XML, as well as elements returned by keywords such as Get Element, can be used as the source
argument with other keywords. In addition to an already parsed XML structure, other keywords also accept paths to XML files and strings containing XML similarly as Parse XML. Notice that keywords that modify XML do not write those changes back to disk even if the source would be given as a path to a file. Changes must always saved explicitly using Save XML keyword.
When the source is given as a path to a file, the forward slash character (/
) can be used as the path separator regardless the operating system. On Windows also the backslash works, but it the test data it needs to be escaped by doubling it (\\
). Using the built-in variable ${/}
naturally works too.
By default this library uses Python's standard ElementTree module for parsing XML, but it can be configured to use lxml module instead when importing the library. The resulting element structure has same API regardless which module is used for parsing.
The main benefits of using lxml is that it supports richer xpath syntax than the standard ElementTree and enables using Evaluate Xpath keyword. It also preserves the doctype and possible namespace prefixes saving XML.
The following simple example demonstrates parsing XML and verifying its contents both using keywords in this library and in BuiltIn and Collections libraries. How to use xpath expressions to find elements and what attributes the returned elements contain are discussed, with more examples, in Finding elements with xpath and Element attributes sections.
In this example, as well as in many other examples in this documentation, ${XML}
refers to the following example XML document. In practice ${XML}
could either be a path to an XML file or it could contain the XML itself.
<example> <first id="1">text</first> <second id="2"> <child/> </second> <third> <child>more text</child> <second id="child"/> <child><grandchild/></child> </third> <html> <p> Text with <b>bold</b> and <i>italics</i>. </p> </html> </example>
${root} = | Parse XML | ${XML} | ||
Should Be Equal | ${root.tag} | example | ||
${first} = | Get Element | ${root} | first | |
Should Be Equal | ${first.text} | text | ||
Dictionary Should Contain Key | ${first.attrib} | id | ||
Element Text Should Be | ${first} | text | ||
Element Attribute Should Be | ${first} | id | 1 | |
Element Attribute Should Be | ${root} | id | 1 | xpath=first |
Element Attribute Should Be | ${XML} | id | 1 | xpath=first |
Notice that in the example three last lines are equivalent. Which one to use in practice depends on which other elements you need to get or verify. If you only need to do one verification, using the last line alone would suffice. If more verifications are needed, parsing the XML with Parse XML only once would be more efficient.
ElementTree, and thus also this library, supports finding elements using xpath expressions. ElementTree does not, however, support the full xpath standard. The supported xpath syntax is explained below and ElementTree documentation provides more details. In the examples ${XML}
refers to the same XML structure as in the earlier example.
If lxml support is enabled when importing the library, the whole xpath 1.0 standard is supported. That includes everything listed below but also lot of other useful constructs.
When just a single tag name is used, xpath matches all direct child elements that have that tag name.
${elem} = | Get Element | ${XML} | third |
Should Be Equal | ${elem.tag} | third | |
@{children} = | Get Elements | ${elem} | child |
Length Should Be | ${children} | 2 |
Paths are created by combining tag names with a forward slash (/
). For example, parent/child
matches all child
elements under parent
element. Notice that if there are multiple parent
elements that all have child
elements, parent/child
xpath will match all these child
elements.
${elem} = | Get Element | ${XML} | second/child |
Should Be Equal | ${elem.tag} | child | |
${elem} = | Get Element | ${XML} | third/child/grandchild |
Should Be Equal | ${elem.tag} | grandchild |
An asterisk (*
) can be used in paths instead of a tag name to denote any element.
@{children} = | Get Elements | ${XML} | */child |
Length Should Be | ${children} | 3 |
The current element is denoted with a dot (.
). Normally the current element is implicit and does not need to be included in the xpath.
The parent element of another element is denoted with two dots (..
). Notice that it is not possible to refer to the parent of the current element.
${elem} = | Get Element | ${XML} | */second/.. |
Should Be Equal | ${elem.tag} | third |
Two forward slashes (//
) mean that all sub elements, not only the direct children, are searched. If the search is started from the current element, an explicit dot is required.
@{elements} = | Get Elements | ${XML} | .//second |
Length Should Be | ${elements} | 2 | |
${b} = | Get Element | ${XML} | html//b |
Should Be Equal | ${b.text} | bold |
Predicates allow selecting elements using also other criteria than tag names, for example, attributes or position. They are specified after the normal tag name or path using syntax path[predicate]
. The path can have wildcards and other special syntax explained earlier. What predicates the standard ElementTree supports is explained in the table below.
Predicate | Matches | Example |
---|---|---|
@attrib | Elements with attribute attrib . |
second[@id] |
@attrib="value" | Elements with attribute attrib having value value . |
*[@id="2"] |
position | Elements at the specified position. Position can be an integer (starting from 1), expression last() , or relative expression like last() - 1 . |
third/child[1] |
tag | Elements with a child element named tag . |
third/child[grandchild] |
Predicates can also be stacked like path[predicate1][predicate2]
. A limitation is that possible position predicate must always be first.
All keywords returning elements, such as Parse XML, and Get Element, return ElementTree's Element objects. These elements can be used as inputs for other keywords, but they also contain several useful attributes that can be accessed directly using the extended variable syntax.
The attributes that are both useful and convenient to use in the test data are explained below. Also other attributes, including methods, can be accessed, but that is typically better to do in custom libraries than directly in the test data.
The examples use the same ${XML}
structure as the earlier examples.
The tag of the element.
${root} = | Parse XML | ${XML} |
Should Be Equal | ${root.tag} | example |
The text that the element contains or Python None
if the element has no text. Notice that the text does not contain texts of possible child elements nor text after or between children. Notice also that in XML whitespace is significant, so the text contains also possible indentation and newlines. To get also text of the possible children, optionally whitespace normalized, use Get Element Text keyword.
${1st} = | Get Element | ${XML} | first |
Should Be Equal | ${1st.text} | text | |
${2nd} = | Get Element | ${XML} | second/child |
Should Be Equal | ${2nd.text} | ${NONE} | |
${p} = | Get Element | ${XML} | html/p |
Should Be Equal | ${p.text} | \n${SPACE*6}Text with${SPACE} |
The text after the element before the next opening or closing tag. Python None
if the element has no tail. Similarly as with text
, also tail
contains possible indentation and newlines.
${b} = | Get Element | ${XML} | html/p/b |
Should Be Equal | ${b.tail} | ${SPACE}and${SPACE} |
A Python dictionary containing attributes of the element.
${2nd} = | Get Element | ${XML} | second |
Should Be Equal | ${2nd.attrib['id']} | 2 | |
${3rd} = | Get Element | ${XML} | third |
Should Be Empty | ${3rd.attrib} |
ElementTree and lxml handle possible namespaces in XML documents by adding the namespace URI to tag names in so called Clark Notation. That is inconvenient especially with xpaths, and by default this library strips those namespaces away and moves them to xmlns
attribute instead. That can be avoided by passing keep_clark_notation
argument to Parse XML keyword. Alternatively Parse XML supports stripping namespace information altogether by using strip_namespaces
argument. The pros and cons of different approaches are discussed in more detail below.
If an XML document has namespaces, ElementTree adds namespace information to tag names in Clark Notation (e.g. {http://ns.uri}tag
) and removes original xmlns
attributes. This is done both with default namespaces and with namespaces with a prefix. How it works in practice is illustrated by the following example, where ${NS}
variable contains this XML document:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> <xsl:template match="/"> <html></html> </xsl:template> </xsl:stylesheet>
${root} = | Parse XML | ${NS} | keep_clark_notation=yes |
Should Be Equal | ${root.tag} | {http://www.w3.org/1999/XSL/Transform}stylesheet | |
Element Should Exist | ${root} | {http://www.w3.org/1999/XSL/Transform}template/{http://www.w3.org/1999/xhtml}html | |
Should Be Empty | ${root.attrib} |
As you can see, including the namespace URI in tag names makes xpaths really long and complex.
If you save the XML, ElementTree moves namespace information back to xmlns
attributes. Unfortunately it does not restore the original prefixes:
<ns0:stylesheet xmlns:ns0="http://www.w3.org/1999/XSL/Transform"> <ns0:template match="/"> <ns1:html xmlns:ns1="http://www.w3.org/1999/xhtml"></ns1:html> </ns0:template> </ns0:stylesheet>
The resulting output is semantically same as the original, but mangling prefixes like this may still not be desirable. Notice also that the actual output depends slightly on ElementTree version.
Because the way ElementTree handles namespaces makes xpaths so complicated, this library, by default, strips namespaces from tag names and moves that information back to xmlns
attributes. How this works in practice is shown by the example below, where ${NS}
variable contains the same XML document as in the previous example.
${root} = | Parse XML | ${NS} | ||
Should Be Equal | ${root.tag} | stylesheet | ||
Element Should Exist | ${root} | template/html | ||
Element Attribute Should Be | ${root} | xmlns | http://www.w3.org/1999/XSL/Transform | |
Element Attribute Should Be | ${root} | xmlns | http://www.w3.org/1999/xhtml | xpath=template/html |
Now that tags do not contain namespace information, xpaths are simple again.
A minor limitation of this approach is that namespace prefixes are lost. As a result the saved output is not exactly same as the original one in this case either:
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"> <template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"></html> </template> </stylesheet>
Also this output is semantically same as the original. If the original XML had only default namespaces, the output would also look identical.
This library handles namespaces same way both when using lxml and when not using it. There are, however, differences how lxml internally handles namespaces compared to the standard ElementTree. The main difference is that lxml stores information about namespace prefixes and they are thus preserved if XML is saved. Another visible difference is that lxml includes namespace information in child elements got with Get Element if the parent element has namespaces.
Because namespaces often add unnecessary complexity, Parse XML supports stripping them altogether by using strip_namespaces=True
. When this option is enabled, namespaces are not shown anywhere nor are they included if XML is saved.
Attributes in XML documents are, by default, in the same namespaces as the element they belong to. It is possible to use different namespaces by using prefixes, but this is pretty rare.
If an attribute has a namespace prefix, ElementTree will replace it with Clark Notation the same way it handles elements. Because stripping namespaces from attributes could cause attribute conflicts, this library does not handle attribute namespaces at all. Thus the following example works the same way regardless how namespaces are handled.
${root} = | Parse XML | <root id="1" ns:id="2" xmlns:ns="http://my.ns"/> | |
Element Attribute Should Be | ${root} | id | 1 |
Element Attribute Should Be | ${root} | {http://my.ns}id | 2 |
Some keywords accept arguments that are handled as Boolean values true or false. If such an argument is given as a string, it is considered false if it is an empty string or equal to FALSE
, NONE
, NO
, OFF
or 0
, case-insensitively. Other strings are considered true regardless their value, and other argument types are tested using the same rules as in Python.
True examples:
Parse XML | ${XML} | keep_clark_notation=True | # Strings are generally true. |
Parse XML | ${XML} | keep_clark_notation=yes | # Same as the above. |
Parse XML | ${XML} | keep_clark_notation=${TRUE} | # Python True is true. |
Parse XML | ${XML} | keep_clark_notation=${42} | # Numbers other than 0 are true. |
False examples:
Parse XML | ${XML} | keep_clark_notation=False | # String false is false. |
Parse XML | ${XML} | keep_clark_notation=no | # Also string no is false. |
Parse XML | ${XML} | keep_clark_notation=${EMPTY} | # Empty string is false. |
Parse XML | ${XML} | keep_clark_notation=${FALSE} | # Python False is false. |
Considering string NONE
false is new in Robot Framework 3.0.3 and considering also OFF
and 0
false is new in Robot Framework 3.1.
Some keywords, for example Elements Should Match, support so called glob patterns where:
* |
matches any string, even an empty string |
? |
matches any single character |
[chars] |
matches one character in the bracket |
[!chars] |
matches one character not in the bracket |
[a-z] |
matches one character from the range in the bracket |
[!a-z] |
matches one character not from the range in the bracket |
Unlike with glob patterns normally, path separator characters /
and \
and the newline character \n
are matches by the above wildcards.
Support for brackets like [abc]
and [!a-z]
is new in Robot Framework 3.1
Arguments | Documentation |
---|---|
use_lxml=False | Import library with optionally lxml mode enabled. By default this library uses Python's standard ElementTree module for parsing XML. If Using lxml requires that the lxml module is installed on the system. If lxml mode is enabled but the module is not installed, this library will emit a warning and revert back to using the standard ElementTree. |
Keyword | Arguments | Documentation | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Add Element | source, element, index=None, xpath=. | Adds a child element to the specified element. The element to whom to add the new element is specified using The Examples using
Use Remove Element or Remove Elements to remove elements. | |||||||||||||||||||||||||||||||||||
Clear Element | source, xpath=., clear_tail=False | Clears the contents of the specified element. The element to clear is specified using Clearing the element means removing its text, attributes, and children. Element's tail text is not removed by default, but that can be changed by giving Examples using
Use Remove Element to remove the whole element. | |||||||||||||||||||||||||||||||||||
Copy Element | source, xpath=. | Returns a copy of the specified element. The element to copy is specified using If the copy or the original element is modified afterwards, the changes have no effect on the other. Examples using
| |||||||||||||||||||||||||||||||||||
Element Attribute Should Be | source, name, expected, xpath=., message=None | Verifies that the specified attribute is The element whose attribute is verified is specified using The keyword passes if the attribute To test that the element does not have a certain attribute, Python Examples using
See also Element Attribute Should Match and Get Element Attribute. | |||||||||||||||||||||||||||||||||||
Element Attribute Should Match | source, name, pattern, xpath=., message=None | Verifies that the specified attribute matches This keyword works exactly like Element Attribute Should Be except that the expected value can be given as a pattern that the attribute of the element must match. Pattern matching is similar as matching files in a shell with Examples using
| |||||||||||||||||||||||||||||||||||
Element Should Exist | source, xpath=., message=None | Verifies that one or more element match the given Arguments See also Element Should Not Exist as well as Get Element Count that this keyword uses internally. | |||||||||||||||||||||||||||||||||||
Element Should Not Exist | source, xpath=., message=None | Verifies that no element match the given Arguments See also Element Should Exist as well as Get Element Count that this keyword uses internally. | |||||||||||||||||||||||||||||||||||
Element Should Not Have Attribute | source, name, xpath=., message=None | Verifies that the specified element does not have attribute The element whose attribute is verified is specified using The keyword fails if the specified element has attribute Examples using
See also Get Element Attribute, Get Element Attributes, Element Text Should Be and Element Text Should Match. | |||||||||||||||||||||||||||||||||||
Element Text Should Be | source, expected, xpath=., normalize_whitespace=False, message=None | Verifies that the text of the specified element is The element whose text is verified is specified using The text to verify is got from the specified element using the same logic as with Get Element Text. This includes optional whitespace normalization using the The keyword passes if the text of the element is equal to the Examples using
| |||||||||||||||||||||||||||||||||||
Element Text Should Match | source, pattern, xpath=., normalize_whitespace=False, message=None | Verifies that the text of the specified element matches This keyword works exactly like Element Text Should Be except that the expected value can be given as a pattern that the text of the element must match. Pattern matching is similar as matching files in a shell with Examples using
| |||||||||||||||||||||||||||||||||||
Element To String | source, xpath=., encoding=None | Returns the string representation of the specified element. The element to convert to a string is specified using By default the string is returned as Unicode. If See also Log Element and Save XML. | |||||||||||||||||||||||||||||||||||
Elements Should Be Equal | source, expected, exclude_children=False, normalize_whitespace=False | Verifies that the given Both The keyword passes if the All texts inside the given elements are verified, but possible text outside them is not. By default texts must match exactly, but setting Examples using
The last example may look a bit strange because the See also Elements Should Match. | |||||||||||||||||||||||||||||||||||
Elements Should Match | source, expected, exclude_children=False, normalize_whitespace=False | Verifies that the given This keyword works exactly like Elements Should Be Equal except that texts and attribute values in the expected value can be given as patterns. Pattern matching is similar as matching files in a shell with Examples using
See Elements Should Be Equal for more examples. | |||||||||||||||||||||||||||||||||||
Evaluate Xpath | source, expression, context=. | Evaluates the given xpath expression and returns results. The element in which context the expression is executed is specified using The xpath expression to evaluate is given as Examples using
This keyword works only if lxml mode is taken into use when importing the library. | |||||||||||||||||||||||||||||||||||
Get Child Elements | source, xpath=. | Returns the child elements of the specified element as a list. The element whose children to return is specified using All the direct child elements of the specified element are returned. If the element has no children, an empty list is returned. Examples using
| |||||||||||||||||||||||||||||||||||
Get Element | source, xpath=. | Returns an element in the The The keyword fails if more, or less, than one element matches the Examples using
Parse XML is recommended for parsing XML when the whole structure is needed. It must be used if there is a need to configure how XML namespaces are handled. Many other keywords use this keyword internally, and keywords modifying XML are typically documented to both to modify the given source and to return it. Modifying the source does not apply if the source is given as a string. The XML structure parsed based on the string and then modified is nevertheless returned. | |||||||||||||||||||||||||||||||||||
Get Element Attribute | source, name, xpath=., default=None | Returns the named attribute of the specified element. The element whose attribute to return is specified using The value of the attribute Examples using
See also Get Element Attributes, Element Attribute Should Be, Element Attribute Should Match and Element Should Not Have Attribute. | |||||||||||||||||||||||||||||||||||
Get Element Attributes | source, xpath=. | Returns all attributes of the specified element. The element whose attributes to return is specified using Attributes are returned as a Python dictionary. It is a copy of the original attributes so modifying it has no effect on the XML structure. Examples using
Use Get Element Attribute to get the value of a single attribute. | |||||||||||||||||||||||||||||||||||
Get Element Count | source, xpath=. | Returns and logs how many elements the given Arguments See also Element Should Exist and Element Should Not Exist. | |||||||||||||||||||||||||||||||||||
Get Element Text | source, xpath=., normalize_whitespace=False | Returns all text of the element, possibly whitespace normalized. The element whose text to return is specified using This keyword returns all the text of the specified element, including all the text its children and grandchildren contain. If the element has no text, an empty string is returned. The returned text is thus not always the same as the text attribute of the element. By default all whitespace, including newlines and indentation, inside the element is returned as-is. If Examples using
See also Get Elements Texts, Element Text Should Be and Element Text Should Match. | |||||||||||||||||||||||||||||||||||
Get Elements | source, xpath | Returns a list of elements in the The Elements matching the Examples using
| |||||||||||||||||||||||||||||||||||
Get Elements Texts | source, xpath, normalize_whitespace=False | Returns text of all elements matching The elements whose text to return is specified using The text of the matched elements is returned using the same logic as with Get Element Text. This includes optional whitespace normalization using the Examples using
| |||||||||||||||||||||||||||||||||||
Log Element | source, level=INFO, xpath=. | Logs the string representation of the specified element. The element specified with The logged string is also returned. | |||||||||||||||||||||||||||||||||||
Parse Xml | source, keep_clark_notation=False, strip_namespaces=False | Parses the given XML file or string into an element structure. The As discussed in Handling XML namespaces section, this keyword, by default, removes namespace information ElementTree has added to tag names and moves it into If you want to strip namespace information altogether so that it is not included even if XML is saved, you can give a true value to Examples:
Use Get Element keyword if you want to get a certain element and not the whole structure. See Parsing XML section for more details and examples. | |||||||||||||||||||||||||||||||||||
Remove Element | source, xpath=, remove_tail=False | Removes the element matching The element to remove from the The keyword fails if Element's tail text is not removed by default, but that can be changed by giving Examples using
| |||||||||||||||||||||||||||||||||||
Remove Element Attribute | source, name, xpath=. | Removes attribute The element whose attribute to remove is specified using It is not a failure to remove a non-existing attribute. Use Remove Element Attributes to remove all attributes and Set Element Attribute to set them. Examples using
Can only remove an attribute from a single element. Use Remove Elements Attribute to remove an attribute of multiple elements in one call. | |||||||||||||||||||||||||||||||||||
Remove Element Attributes | source, xpath=. | Removes all attributes from the specified element. The element whose attributes to remove is specified using Use Remove Element Attribute to remove a single attribute and Set Element Attribute to set them. Examples using
Can only remove attributes from a single element. Use Remove Elements Attributes to remove all attributes of multiple elements in one call. | |||||||||||||||||||||||||||||||||||
Remove Elements | source, xpath=, remove_tail=False | Removes all elements matching The elements to remove from the It is not a failure if Element's tail text is not removed by default, but that can be changed by using Examples using
| |||||||||||||||||||||||||||||||||||
Remove Elements Attribute | source, name, xpath=. | Removes attribute Like Remove Element Attribute but removes the attribute of all elements matching the given | |||||||||||||||||||||||||||||||||||
Remove Elements Attributes | source, xpath=. | Removes all attributes from the specified elements. Like Remove Element Attributes but removes all attributes of all elements matching the given | |||||||||||||||||||||||||||||||||||
Save Xml | source, path, encoding=UTF-8 | Saves the given element to the specified file. The element to save is specified with The file where the element is saved is denoted with The resulting XML file may not be exactly the same as the original:
Use Element To String if you just need a string representation of the element. | |||||||||||||||||||||||||||||||||||
Set Element Attribute | source, name, value, xpath=. | Sets attribute The element whose attribute to set is specified using It is possible to both set new attributes and to overwrite existing. Use Remove Element Attribute or Remove Element Attributes for removing them. Examples using
Can only set an attribute of a single element. Use Set Elements Attribute to set an attribute of multiple elements in one call. | |||||||||||||||||||||||||||||||||||
Set Element Tag | source, tag, xpath=. | Sets the tag of the specified element. The element whose tag to set is specified using Examples using
Can only set the tag of a single element. Use Set Elements Tag to set the tag of multiple elements in one call. | |||||||||||||||||||||||||||||||||||
Set Element Text | source, text=None, tail=None, xpath=. | Sets text and/or tail text of the specified element. The element whose text to set is specified using Element's text and tail text are changed only if new Examples using
Can only set the text/tail of a single element. Use Set Elements Text to set the text/tail of multiple elements in one call. | |||||||||||||||||||||||||||||||||||
Set Elements Attribute | source, name, value, xpath=. | Sets attribute Like Set Element Attribute but sets the attribute of all elements matching the given | |||||||||||||||||||||||||||||||||||
Set Elements Tag | source, tag, xpath=. | Sets the tag of the specified elements. Like Set Element Tag but sets the tag of all elements matching the given | |||||||||||||||||||||||||||||||||||
Set Elements Text | source, text=None, tail=None, xpath=. | Sets text and/or tail text of the specified elements. Like Set Element Text but sets the text or tail of all elements matching the given |