使用 XPath 将 URL 查询字符串解析为参数映射
Posted
技术标签:
【中文标题】使用 XPath 将 URL 查询字符串解析为参数映射【英文标题】:Parsing a URL query string into a map of parameters with XPath 【发布时间】:2021-10-26 21:12:30 【问题描述】:在 XSLT/XPath 3.0 中将 URL 查询字符串解析为 'param': 'value'
映射的最易读的方法是什么?
注意:这是Building a URL query string from a map of parameters with XPath 中描述的函数的反函数。
更新:我没有提到该函数应该支持多值参数,例如a=1&a=2
,并理想地将它们解析为xs:string*
序列。
【问题讨论】:
【参考方案1】:declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
let $querystring := "a=1&b=2&c=3"
return
( tokenize($querystring, "&")
! (let $param := tokenize(., "=")
return map:entry($param[1], $param[2]) )
) => map:merge()
为了支持多个值,您可以应用$options parameter 指定如何处理duplicates
:
declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
let $querystring := "a=1&b=2&a=3"
return
( tokenize($querystring, "&")
! (let $param := tokenize(., "=")
return map:entry($param[1], $param[2]) )
) => map:merge(map:entry('duplicates', 'combine'))
【讨论】:
首先想到的 - 重复的参数名称怎么办? :) 我正在使用的反向 URI 构建函数的版本支持查询参数为map(xs:string, xs:string*)
,这意味着一个参数可以有多个值。那么在这种情况下是否可以将它们解析为xs:string*
序列?
是的,如果处理多个同名参数,则需要有一个可用的映射,并在放置新条目时附加值。 map:put($map, $key, (map:get($map, $key), $value) )
【参考方案2】:
Christian Grün 的另外 2 个回答:
let $querystring := "a=1&b=2&a=3"
return map:merge(
for $query in tokenize($querystring, "&")
let $param := tokenize($query, "=")
return map:entry(head($param), tail($param)),
map 'duplicates': 'combine'
)
另一种解决方案(如果您不想使用 for 子句):
let $querystring := "a=1&b=2&a=3"
return map:merge(
tokenize($querystring, "&")
! array tokenize(., "=")
! map:entry(.(1), .(2)),
map 'duplicates': 'combine'
)
【讨论】:
【参考方案3】:让我们看看 - 要获取的子字符串?并去除任何尾随的 #... 片段标识符 然后在 [&;] 上进行标记(实际上是 [;&] 以获取名称=值对,它们由 & 或(不太常见)分隔; 然后substring-before and after,或者再次tokenize,得到=(name value)的前后 然后分别对名称和值进行uridecode
let $query := substring-after($uri, '?'),
$beforefrag := substring-before($query || '#', '#')
return
tokenize($beforefrag, '[;&]')
! [substring-before(., '='), substring-after(., '=') ]
! map:entry(local:uridecode(.(1), local:uridecode(.(2))
可能会给我们一系列映射条目,我们可以在上面使用 map:merge。
如果我们知道我们的输入经过合理编码,我们可以使用
declare function local:uridecode($input as xs:string?) as xs:string?
parse-xml-fragment(replace($input, '=(..)', '&x$1;'))
;
但更好的版本只是替换两个十六进制字符。真的很不幸,我们没有一个版本的 replace(),它为每个匹配的子表达式调用一个函数参数,ala perl 的 e 标志。```
当然你可以把它放进去
(...) => map:merge()
【讨论】:
以上是关于使用 XPath 将 URL 查询字符串解析为参数映射的主要内容,如果未能解决你的问题,请参考以下文章