@@ -49,9 +49,12 @@ import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider
4949import io.gatehill.imposter.http.HttpExchange
5050import org.apache.logging.log4j.LogManager
5151import org.apache.logging.log4j.Logger
52+ import org.jdom2.Attribute
53+ import org.jdom2.Content
5254import org.jdom2.Document
5355import org.jdom2.Element
5456import org.jdom2.Namespace
57+ import org.jdom2.filter.Filter
5558import org.jdom2.filter.Filters
5659import org.jdom2.input.SAXBuilder
5760import org.jdom2.xpath.XPathExpression
@@ -73,13 +76,17 @@ object BodyQueryUtil {
7376 .build()
7477 )
7578
76- private fun buildXPath (expression : String , xPathNamespaces : List <Namespace > = emptyList()): XPathExpression <* > {
79+ private fun buildXPath (
80+ expression : String ,
81+ xPathNamespaces : List <Namespace > = emptyList(),
82+ filter : Filter <* > = Filters .element()
83+ ): XPathExpression <* > {
7784 val finalXPath = if (expression.startsWith(' !' )) {
7885 normaliseXPathExpression(expression.substring(1 ))
7986 } else {
8087 expression
8188 }
82- return XPathFactory .instance().compile(finalXPath, Filters .element() , emptyMap(), xPathNamespaces)
89+ return XPathFactory .instance().compile(finalXPath, filter , emptyMap(), xPathNamespaces)
8390 }
8491
8592 private fun buildNamespaces (namespaces : Map <String , String >? ) =
@@ -144,14 +151,23 @@ object BodyQueryUtil {
144151 } else {
145152 try {
146153 val document = getRequestXmlDocument(httpExchange, body)
147- selectSingleNode (document, xPath, buildNamespaces(xmlNamespaces))?.value
154+ getXPathValue (document, xPath, buildNamespaces(xmlNamespaces))
148155 } catch (e: Exception ) {
149156 logger.warn(" Error evaluating XPath expression '$xPath ' against request body for ${LogUtil .describeRequest(httpExchange)} " , e)
150157 null
151158 }
152159 }
153160 }
154161
162+ fun getXPathValue (context : Any , expression : String , xPathNamespaces : List <Namespace >): String? {
163+ val xPath = buildXPath(expression, xPathNamespaces, Filters .fpassthrough())
164+ return when (val result = xPath.evaluateFirst(context)) {
165+ is Content -> result.value // matches also Element
166+ is Attribute -> result.value
167+ else -> null
168+ }
169+ }
170+
155171 /* *
156172 * Gets the XML document for XPath queries against the request body.
157173 * The document is cached in the [HttpExchange].
0 commit comments