Tags

    Parsing Responses and other XML with XPATH

    Function Overview

    You can use the Web Services Plug-in to parse any XML with the _FmNx_XPATH_query function, although it is typically used to parse the XML responses from Web Services.

    _FmNx_XPATH_query ( xml_document; xpath_query {; remove_tags; {namespaces_list}} )

    xpath_query supports XPath 1.0 queries and functions and is case sensitive. For more information, please see http://www.w3.org/TR/xpath/.
    remove_tags is either "true" or "false"
    namespace_list is only required for namespaces are defined for nodes in the query. Namespaces are separated by spaces, and each referenced namespace must contain a prefix you define and the namespace url from the XML document: "<prefix1>=<href1> <prefix2>=href2> ..."
    XQuery and XPath 2.0 are not supported.

    Example

    XML:

    Query:

    _FmNx_XPATH_query (
    $_xml_to_parse ;
    "/envns:Envelope/envns:Body/dfns:ServiceResponse/ServiceReturn/ColumnList/Column[2]" ;
    "true" ;
    )

    Result:
    ITEM STATUS

    Note: It is important to create your own namespace prefix references. You MUST use the namespace URLs from the XML, but you should NOT use the same namespace prefixes as found in the XML (e.g. "soapenv=http://schemas.xmlsoap.org/soap/envelope/") as this may confuse the parser.

    Tip: When pasting in a URL from the XML, be sure to exclude the leading quote mark. The quotes should be around the entire "prefix=URL" pair, not just the URL.

    Using the Any Node ("//") shortcut in XPath Queries

    The parser is optimized for queries that use // (for any matching node), and this makes building XPath queries easier. For example, if you are looking for a "Data" node somewhere in a large block of XML, instead of specifying the entire hierarchy, all you need is an XPath query of "//Data".


    Including Namespace Prefixes in XPath Queries

    Failure to properly define namespace prefixes for XPath queries is a common cause of query errors or unexpected results (i.e. 0 or blank). In the XML example shown above, namespace prefixes are needed to map to the prefixed Envelope, Body, and ServiceResponse nodes. Typically you need to look for node prefixes (e.g. "<soapenv:Body>" and then find the corresponding "xmlns" definitions (e.g. xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"). Finally, create your own prefix and include in the XPath Function and map to the URL in the namespace list of the _FmNx_XPATH_query function (e.g. "envns=http://schemas.xmlsoap.org/soap/envelope").

    Note that in the example provided above, no namespace prefix would be needed for the ColumnList, Column, and Data nodes. ServiceReturn also does not need a namespace, since "ns2:" is not used to prefix the ServiceReturn node itself.

    Note: Some XML nodes do not use a prefix but DO set the default namespace using the form <MyNode xmlns="http://DefaultNameSpace">. In this case you must specify the namespace for the node and all its children.

    Example (Find the C element of the first B element)

    XML:
    <C></C>
    </B>
    <B>
    <C type="amphibian">Frog</C>
    </B>
    </A>

    Query:
    _FmNx_XPATH_query (
    $_xml_to_parse ;
    "/A/dfns:B[1]/dfns:C" ;
    "true" ;
    )

    Result:
    Frog

    XML Attributes

    Here's how to find the value of an node's attribute instead of the node content (using the same XML as above).

    Query:
    _FmNx_XPATH_query (
    $_xml_to_parse ;
    "/A/B[2]/C/attribute::type" ;
    "true"
    )

    Result:
    amphibian

    Using XPath 1.0 Functions

    You can use helpful XPath 1.0 functions to obtain information about the XML and to perform advanced parsing tasks.

    Example (Uses the count function to count the number of Column nodes)

    _FmNx_XPATH_query ( $_xml_to_parse ; "count(//Column)" )

    Please see http://www.w3.org/TR/xpath/ for more information about XPath functions.


    Using Element Position in XPath Queries to Find Repeating Data

    The very powerful node position predicate can be used to obtain data from repeating elements in the XML. Predicates in XPath queries are specified in brackets immediately following the node name (e.g. "A[4]"). However, the position number must be specified in the correct place.

    Example:
    <A>
    <B>
    <C></C>
    </B>
    <B>
    <C></C>
    </B>
    </A>

    In the above XML there are multiple C tags however inside a B tag there is only one C tag per B tag. So the thing to do is find the node that is actually repeating and select on it, so use "//B[2]/C" as your XPath query to get the second C.

    If you look for "//C[2]" there is no other C tag to return and you get nothing back (there is no second C tag within a B tag). Similarly you cannot do //A[2]//C to get the second C since that would attempt to get the second A tag in that chunk of xml which does not exist.

    In short, you must specify the sequence only at the tag that is repeating (in this case B).

    Here is a more complex example. The following script determines the number of rows and columns from the XML example at the beginning of this page and loops through the contents of the Data elements accordingly:

    Script Example

    #

    # Define the XML to parse and any necessary namespace references.

    Set Variable [ $_xml_to_parse; Value:MY_TABLE::my_xml ]

    Set Variable [ $_namespaces; Value:"dfns=http://DefaultNamespace envns=http://schemas.xmlsoap.org/soap/envelope/" ]

    #

    # Determine the number of data rows and columns in the XML:

    Set Variable [ $_rows; Value:_FmNx_XPATH_query( $_xml_to_parse ; "count(/envns:Envelope/envns:Body/dfns: ServiceResponse/ServiceReturn/Data/Data)" ; "true"; $_namespaces ) ]

    Set Variable [ $_columns; Value:_FmNx_XPATH_query ( $_xml_to_parse ; "count(/envns:Envelope/envns:Body/dfns: ServiceResponse/ServiceReturn/ColumnList/Column)" ; "true" ; $_namespaces ) ]

    # # Loop through the rows Set Variable [ $_current_row; Value:0 ] Loop

    Set Variable [ $_current_row; Value:$_current_row + 1 ] Exit Loop If [ $_current_row > $_rows ] # # Loop through the columns

    Set Variable [ $_current_column; Value:0 ] Loop

    Set Variable [ $_current_column; Value:$_current_column + 1 ] Exit Loop If [ $_current_column > $_columns ] # $_current_row and $_current_column are used in the XPATH query to define the positions of the XML elements # (e.g. Row 2, Column 1 is "//ServiceReturn/Data[2]/Data[1]")

    Set Variable [ $_result; Value:$_result & "Row " & $_current_row & ", Column " & $_current_column & "="&

    _FmNx_XPATH_query ( $_xml_to_parse ; "/envns:Envelope/envns:Body/dfns:ServiceResponse/ServiceReturn/Data/Data[" & $_current_row & "]" & "/Data[" &

    $_current_column & "]" ; "true" ;

    )& ¶]

    End Loop

    #

    End Loop

    #

    $_namespaces

    Show Custom Dialog [ Title: "Results"; Message: $_result; Buttons: “OK” ] # Exit Script [ ]

    #

    Exit Script [ ]


    Result



    Comments

    /groups/ws/search/index.rss?tag=hotlist/groups/ws/search/?tag=hotWhat’s HotHotListHot!?tag=hot0/groups/ws/sidebar/HotListNo items tagged with hot.hot/groups/ws/search/index.rss?sort=modifiedDate&kind=all&sortDirection=reverse&excludePages=wiki/welcomelist/groups/ws/search/?sort=modifiedDate&kind=all&sortDirection=reverse&excludePages=wiki/welcomeRecent ChangesRecentChangesListUpdates?sort=modifiedDate&kind=all&sortDirection=reverse&excludePages=wiki/welcome0/groups/ws/sidebar/RecentChangesListmodifiedDateallRecent ChangesRecentChangesListUpdateswiki/welcomeNo recent changes.reverse5search