A Gentle Introduction to XPath

MobileTogether uses XPath as its formula and expression language.

If you know how to write formulas in an Excel spreadsheet, you can easily learn how to write XPath formulas or expressions in MobileTogether. You only need to understand a few basic concepts. The XPath builder in MobileTogether makes it easy to construct XPath expressions, just like the formula builder in Excel helps you with writing formulas in your spreadsheets.

So why is it called XPath?

The "X" in XPath comes from its roots in XML, the eXtensible Markup Language, and the Path comes from the fact that you use a path-like format to identify individual pieces of your data. Any data source that you access in MobileTogether is represented as a little tree structure on the right side of your MobileTogether Designer window under “Page Sources”. Each tree structure starts with a root that has a name, such as $XML1 or $DB1, and then there are individual pieces of data – called elements – underneath that root. These elements are nested in a logical fashion, so they are best represented as trees in which you can collapse and expand every element to see what is underneath. And the best thing about MobileTogether is: it doesn’t matter if the underlying data comes from a database, an XML document, a web service, or any other data source – they are all presented in the same way and can be accessed in the same way.

What XPath allows you to do is navigate through these tree structures to associate your data elements with user interface objects on the screens of your mobile devices. It is very similar to how you would navigate through a directory tree in your file system on a computer’s hard drive. Irrespective of whether you are used to Windows, Linux, or MacOS, files on your hard drive can always be accessed through a path, such as:

C:\Users\Spock\Documents\ScienceRecords 	(Windows)
/Users/Kirk/Documents/BeautifulAlienWomen	(Linux/Mac)

So let’s look at an example XPath expression by comparison:

$DB1/salesdata/region/month/gadgets

As you can see, it is exactly the same idea. You use XPath to navigate through data tree structures the same way you use path expressions to navigate through your file system on a computer’s hard drive. XPath uses the / (forward slash) character to separate individual elements on the path just like Linux and MacOS use that character to separate directories.

Interestingly, this analogy to directory paths also holds for two very common abbreviations in XPath: just like a single period . refers to the current directory in a file system, the . refers to the current element in XPath, and similarly the double period .. that refers to a parent directory in a file system also refers to the parent element in XPath.

Attributes

If your data source happens to be an XML document, or XML data that is being returned by a web service, then the data that is contained in that tree structure comes in two different flavors: elements and attributes. Elements are the core data items in XML and can be nested, so an element can have children in the tree structure. Attributes, on the other hand, are simple data values that are attached to elements. In the trees under Page Sources you will see that attributes are shown with an = (equal sign) before their name. That’s because in an XML document, attributes are written as, e.g., color=”green”.

When you want to refer to attributes in an XPath expression, you need to write an @ (at-sign) before their name:

$XML1/salesdata/region/@name

Otherwise, you can do the same thing with elements and attributes, i.e., you can use both in calculations or graph their values in a chart, and you can assign both to user interface objects in a MobileTogether design.

Predicates

Sometimes it is not enough to simply specify the path to an element in your data. What you really want to do is to select some of the data that matches a certain criteria in order to, e.g., show it in a graph or present it to the user in a table.

If you have ever worked with relational databases, this would be equivalent to the typical WHERE clause in a SQL statement. It lets you pick out the data from your database that matches a certain criteria

The equivalent concept in XPath is called “Predicates”. An XPath predicate allows you to specify selection criteria that will only pick certain elements that match the specified criteria. Predicates are entered as a logical test enclosed by [] (square brackets), for example:

$XML1/salesdata/region[@name=”East”]/Month

The way to interpret this statement is: in the $XML1 data source go to the salesdata element, then go to its child element region and select only those regions where the attribute name is equivalent to “East”, and then select their respective child element Month.

Operators

Now we’ve said in the beginning that XPath is a full expression language. That means it not only lets you select certain pieces of data – it actually enables you to do all the typical mathematical operations with the data to calculate new values. Just like formulas in Excel allow you to calculate new values from your existing data, you can do the exact same thing with XPath expressions in MobileTogether.

Let’s say you want to create a mobile invoicing solution and want to display the total amount for a line item in your mobile form:

$DB1/sales/invoice/item/quantity * $DB1/sales/invoice/item/price

Assuming that your data structure has separate elements for quantity and price (that may be editable by the user), you can then simply calculate the total amount for that line item with the above multiplication using * (asterisk).

One of the really cool capabilities of XPath is that you can save yourself a lot of typing by doing the multiplication right within the XPath by using parenthesis when you get to the right point in the path, so this shortened version is equivalent to the above expression:

$DB1/sales/invoice/item/(quantity * price)

Similarly, you can use + (plus) and - (minus) as mathematical operators. But you have to use a different symbol for the division. Since we are already using the / (forward slash) to separate individual elements on a path, we cannot use the same character for a division. Therefore, the operator for a division in XPath is the word div for a real-number division and idiv for an integer division (i.e. if you want the result to be a whole/integer number rather than a real number).

Also, it is a good practice – and sometimes essential – to put spaces around your operators to ensure that they are not mistaken for being part of an element or attribute name. This is especially true for the - (minus) operator.

Sequences

One important difference between XPath and directory paths is that while a directory path expression typically identifies only one particular file or directory, an XPath expression can actually reference more than one data node (i.e., an element or an attribute). In fact, every XPath expression always returns a sequence of nodes as its result.

This is most easily understood if you consider that most databases contain rows of data that have a similar structure, just as most XML documents at their core contain a series of elements that have the same name and share a similar structure. XPath has been created to enable a developer to easily work with such data sets – so being able to address an entire set of nodes at once has huge benefits, as we will see in the next few chapters.

At the same time, sometimes it may become necessary to explicitly define sequences in an XPath expression, and you would do that by enumerating the values in the following form:

(1, 2, 3, 4, 5)

Sequences are ordered, so the above sequence is distinctly different from the sequence (3, 5, 2, 4, 1). Sequences can contain nodes from your data, as well as constant numerical values or constant string values.

For example, a possible sequence of strings would look like this:

("a", "b", "c", "d", "e")

Last, but not least, you can specify ordered sequences of numeric values using the range operator to:

(1 to 5)

This is equivalent to the sequence (1, 2, 3, 4, 5) – as you can see, this range operator can be used for quickly constructing sequences of numerical values that would be too cumbersome to enumerate by hand as the numbers get larger.

for Expression

If you have worked with any other programming language in the past, you will recognize the for loop as being a prevalent tool that exists in most modern languages in some form, and it is also an integral part of the XPath expression language.

In its simplest form, a for expression in XPath allows you to iterate over a sequence of values or nodes using a temporary loop variable that gets defined directly in the for expression. For example, the expression

for $i in (1 to 10) return 2 * $i

will produce the numeric sequence (2, 4, 6, 8, 10, 12, 14, 16, 18, 20) by iterating over the original sequence (1 to 10) using the variable $i and then calculating 2 * $i for each data point in the sequence.

Now that we know that any XPath expression can return a sequence of nodes, we can also utilize the for expression to iterate over those nodes and conduct some mathematical operation. For example, to iterate over all line items in an invoice and calculate the respective amount for that line item, we could use this expression:

for $x in $DB1/sales/invoice/item return $x/price * $x/quantity

In this case, $x will be our loop variable that iterates over each item element, and this expression will return a sequence that contains the amounts for each line in our invoice. Let’s assume we have the following two item elements in our invoice source data:

<item>
  <quantity>5</quantity>
  <price>12.50</price>
</item>
<item>
  <quantity>3</quantity>
  <price>27.85</price>
</item>

Then the previous XPath expression will return the sequence (62.5 83.55), which are the respective amounts for each line item on the invoice.

Functions

Functions in XPath work exactly like functions in an Excel formula or in most other programming languages: you call a function using its name and passing a set of function parameters in parenthesis (). For example, to sum up the sequence (3, 9, 14) you would write:

sum( (3, 9, 14) )

This would give us the result of 26. Please note that in this case the outer parenthesis are part of the function call to the sum() function, whereas the inner parenthesis are part of the sequence that we are passing to the function as a single parameter.

Similarly, we can now calculate the invoice total from the previous example by adding up all the line items:

sum( for $x in $DB1/sales/invoice/item
    return $x/price * $x/quantity )

This can be very useful, e.g., for building interactive forms inside a mobile solution where you can show data value for totals that will dynamically change as the user enters data into the form.

XPath contains a large number of built-in functions for numeric values (e.g., round, abs, floor, etc.), string manipulation (e.g., concat, lower-case, contains, replace), durations, dates, and times, as well as aggregate operations on sequences (e.g., count, sum, avg, min, max). The XPath builder in MobileTogether makes it easy to write XPath expressions using these functions, because it includes a convenient directory of all available functions with a short description and information on the required parameters. The functions are shown in logical groups, so it is easy to find the function needed for your particular use-case.

if Expression

It is often necessary in programming languages – as well as in expression languages – to decide on a different way to compute a particular result depending on whether a certain criteria is met or not. This is where the if statement, which allows you to define alternative outcomes based on a test-criteria that you specify, comes into play.

In XPath the if statement takes the following form:

if ( test-expression ) then expression else expression

where test-expression is a logical XPath expression that returns true or false.

For example, we can use such a statement in MobileTogether to make the text color of a label or edit field dependent on the numeric value contained in the data. Let’s say we have an element from our data source associated with an edit field. We can select that edit field and go to the properties tab, where we can select the Text Color property. Instead of defining the color with the color picker, we can click on the toolbar XPath icon and decide to define the text color of that input field via an XPath expression:

if ( $MT_ControlValue >= 0 ) then "green" else "red"

Here we are using one of the built-in MobileTogether variables to refer to the current control and we are testing if the value is greater than or equal to zero.

Depending on the outcome of that test, the result will be either “green” or “red,” and our text color will change dynamically based on the user’s input.

Similarly, there are many more built-in variables that all start with $MT_ that let you make decisions based on the screen size of the device, operating system, language, and many other factors. All of those built-in global variables can be viewed in the Global Variables dialog on the Project menu in MobileTogether Designer.

XQuery

Until this point we have spoken mainly about XPath for historic reasons, since it is the more commonly known XML-based expression language and has been around for 15 years. However, in addition to XPath, MobileTogether also supports the more powerful XQuery language. XQuery is a true superset of XPath, meaning that every single valid XPath expression is also a valid XQuery expression. XQuery, however, adds a couple of additional powerful constructs that allow you to do much more and let you manipulate or construct entire XML documents on the fly.

FLWOR Expression

The most important XQuery expression is the so-called FLWOR expression. FLWOR is an acronym that stands for “For-Let-Where-Order-Return” and is commonly pronounced “flower”. It is functionally equivalent to the SQL SELECT statement that has similar clauses, such as FROM, WHERE, ORDER BY, etc. The FLWOR expression allows us to query XML and database data much more efficiently and powerfully than with plain XPath expressions, and it forms the cornerstone of XQuery.

We have already encountered the for part of the expression in our previous discussion of XPath, so that part of the FLWOR expression will be a familiar start. Similarly, we have seen the return clause in the same for expression before. However, XQuery greatly expands the flexibility of the return clause by allowing you to create entire XML trees from scratch using constructors. Essentially, as before, the return clause gets evaluated for each item in the for loop, but instead of just producing one value in a sequence, you can now build an entire XML sub-tree, as we will see in some of the examples below.

The purpose of the let clause of the FLWOR expression is to define additional variables that we can later use to build our result. This could be from the same data source or even from a different data source, but, e.g., use the loop variable to select certain elements from the other source.

For example, assuming one data source contains information about departments in an organization, and another data source contains information about employees, this could be the beginning of a FLWOR expression that selects employees from a particular set of departments:

for $d in $DEPARTMENTS/depts/deptno
let $e := $EMPLOYEES/emps/emp[deptno = $d]

The where clause allows us to filter the data based on certain criteria – similar to how we’ve used predicates in pure XPath expressions before. For example, we can use that to filter departments based on the number of employees they have:

for $d in $DEPARTMENTS/depts/deptno
let $e := $EMPLOYEES/emps/emp[deptno = $d]
where count($e) >= 10

Finally, the order by clause allows us to sort the result by any desired criteria, which is especially useful when building resulting new XML documents.

Now let’s put together the entire FLWOR expression using the previously mentioned two data sources with departments and employees. For example, we could generate a new data table to display in a mobile solution that would provide aggregate information on headcount and average salary for those departments that have more than 10 employees:

for $d in $DEPARTMENTS/depts/deptno
let $e := $EMPLOYEES/emps/emp[deptno = $d]
where count($e) >= 10
order by avg($e/salary) descending
return
<big-dept>
   { $d,
      <headcount>{count($e)}</headcount>,
      <avgsal>{avg($e/salary)}</avgsal>
   }
</big-dept>

In another example, using our previous data about mobile invoices with line items, we can now expand on this and loop over multiple invoices after a certain date to calculate their totals and then build a table of ordered results that we can display with the largest invoice total first and the smallest invoice last:

for $inv in $DB1/sales/invoice
let $total := sum (for $x in item return $x/price * $x/quantity)
	where $inv/date >= "2014-01-01"
	order by $total descending
	return <invtotal>{ $total }</invtotal>

As you can see, the flexibility and power of these XQuery expressions is much greater than what we could previously accomplish with XPath alone. However, with additional power also comes increased complexity, so it can take a while until you’ve mastered all of XQuery.

At the same time, the built-in XPath & XQuery builder and evaluator in MobileTogether can assist you greatly in writing proper expressions and testing them with your data. Combined with the powerful simulator that lets you run your mobile apps directly in the MobileTogether Designer, you can test and debug your data selection via XPath and XQuery easily and build powerful mobile apps much more rapidly than with any other approach.

Summary

In this document we have provided a gentle introduction to the most important concepts of XPath and XQuery to help you get started working with data in MobileTogether. We have touched upon the basic concepts of XPath expressions and some of the more powerful XQuery capabilities, which should enable you to create powerful data selections in your mobile workflow, produce exact charts of your data, and customize the user interface of your mobile solution in response to specific data items, as needed.

However, this document is just a starting point and does not attempt to be a full tutorial or explain every aspect of these languages. You can learn more in our comprehensive, free online XPath Training course, which is appropriate for beginners as well as advanced users.

MobileTogether supports the full XPath 3.0 and XQuery 3.0 languages. The benefit of using an international standard, such as XPath and XQuery, is that a lot of developers may have already learned XPath in the past when they worked with XML, XSLT, or XML Schema. So the ability to reuse that know-how in MobileTogether is a big bonus for them. And upgrading your know-how from XPath 1.0 or 2.0 to 3.0 is an easy process.

Also, XPath and XQuery are standards developed by the W3C rather than being a proprietary language invented by one company, so learning these standards will be helpful in other contexts as well.

For the full specification of XPath 3.0 and XQuery 3.0, please see the following technical specification documents:

Last, but not least, using XPath and XQuery in MobileTogether means that you can easily use XMLSpy to prototype, develop, and debug more complex XPath and XQuery expressions, if you need to go the extra mile. XMLSpy provides a full XPath evaluator and XQuery debugger, including a profiler for performance optimization.

To learn more about XPath 3.0 and XQuery 3.0 please refer to Altova’s online training and documentation pages. Also, feel free to ask XPath and XQuery related questions in the MobileTogether support forum at https://support.mobiletogether.com/