{ 'param': 'value' }
在 XSLT/XPath 3.0 中将URL 查询字符串解析为映射的最易读的方法是什么?
注意:这是使用 XPath 从参数映射构建 URL 查询字符串中描述的函数的反函数。
更新:我没有提到该函数应该支持多值参数,例如a=1&a=2
,并理想地将它们解析为一个xs:string*
序列。
{ 'param': 'value' }
在 XSLT/XPath 3.0 中将URL 查询字符串解析为映射的最易读的方法是什么?
注意:这是使用 XPath 从参数映射构建 URL 查询字符串中描述的函数的反函数。
更新:我没有提到该函数应该支持多值参数,例如a=1&a=2
,并理想地将它们解析为一个xs:string*
序列。
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 参数指定如何处理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'))
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' }
)
让我们看看 - 要获取的子字符串?并去除任何尾随的 #... 片段标识符,然后在 [&;] 上进行标记(实际上是 [;&] 以获取名称=值对,它们由 & 或(不太常见)分隔;然后是 substring-before 和 after,或标记化再次,要在 =(名称值)之前和之后获取,然后分别对名称和值进行 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()