问题
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
回答1:
The following XPath 2.0 expression expresses the required selection:
/*/*/*[From[matches($pPat, replace(., '\*', '.*'))]]
Explanation:
The
$pPat
variable contains the search pattern (such as 'EBAY', 'AMAZON', etc.).The standard XPath 2.0 function
matches()
is used to match the value of anyFrom
element to the string pattern.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>
来源:https://stackoverflow.com/questions/539781/xpath-search-based-on-dynamic-regular-expressions