XPath search based on dynamic regular expressions
Asked Answered
H

1

2

I have an XML like the one below:

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration>
        <Destinations>
            <Destination name="DEST1" >
                <From>AMA*</From>
            </Destination>

            <Destination name="DEST2" >
                <From>AMAZON</From>
            </Destination>

                           <Destination name="DEST3" >
                <From>EBAY</From>
            </Destination>

                           <Destination name="DEST4" >
                <From>*</From>
            </Destination>

        </Destinations>
    </Configuration>

I want to query and find out all desintations that match a provided input.

If i specify EBAY i want the xpath to return the node name = DEST3 and DEST4 (which doesn't care about the value) but if i specify AMAZON it needs to return DEST1, DEST2 and DEST4 as AMA* in DEST1 supports wild card character.

so far my XPath looks like this:

/Destination[(From = '' or From = '*' ) )]/@name

If input is specified i create the XPATH expressions dynamically and slot the incoming value in the field

I have other elements in my XML besides From.

Appreciate if anyone could give pointers on this.

Thanks, Manglu

Haemin answered 12/2, 2009 at 2:36 Comment(0)
J
7

The following XPath 2.0 expression expresses the required selection:

  /*/*/*[From[matches($pPat, replace(., '\*', '.*'))]]

Explanation:

  1. The $pPat variable contains the search pattern (such as 'EBAY', 'AMAZON', etc.).

  2. The standard XPath 2.0 function matches() is used to match the value of any From element to the string pattern.

  3. The value of any From element is converted to a standard regular expression as supported by XPath 2.0. For this purpose, any occurence of '*' (escaped as "\*" in order not to be taken as the special char '*' used in regexs but as a normal character) is replaced by the string ".*"

Testing:

I have used the following XSLT 2.0 transformation and verified that the above XPath 2.0 expression selects the elements as expected. To use it, replace the value of the global parameter $pPat with any desired value.

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes"/>

    <xsl:param name="pPat" as="xs:string"
     select="'AMAZON'"/>

    <xsl:variable name="vsrchResult" as="element()*"
     select="/*/*/*[From[matches($pPat, replace(., '\*', '.*'))]]"/>

    <xsl:template match="/">
      <xsl:copy-of select="$vsrchResult"/>
    </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the originally-provided XML document:

<Configuration>
    <Destinations>
        <Destination name="DEST1" >
            <From>AMA*</From>
        </Destination>
        <Destination name="DEST2" >
            <From>AMAZON</From>
        </Destination>
        <Destination name="DEST3" >
            <From>EBAY</From>
        </Destination>
        <Destination name="DEST4" >
            <From>*</From>
        </Destination>
    </Destinations>
</Configuration>

the required output is produced:

<Destination name="DEST1">
            <From>AMA*</From>
        </Destination><Destination name="DEST2">
            <From>AMAZON</From>
        </Destination><Destination name="DEST4">
            <From>*</From>
        </Destination>
Jessicajessie answered 12/2, 2009 at 4:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.