3

{ 'param': 'value' }在 XSLT/XPath 3.0 中将URL 查询字符串解析为映射的最易读的方法是什么?

注意:这是使用 XPath 从参数映射构建 URL 查询字符串中描述的函数的反函数。

更新:我没有提到该函数应该支持多值参数,例如a=1&a=2,并理想地将它们解析为一个xs:string*序列。

4

3 回答 3

2
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'))
于 2021-08-26T21:03:18.127 回答
1

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' }
)
于 2021-08-28T13:24:24.280 回答
0

让我们看看 - 要获取的子字符串?并去除任何尾随的 #... 片段标识符,然后在 [&;] 上进行标记(实际上是 [;&] 以获取名称=值对,它们由 & 或(不太常见)分隔;然后是 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()
于 2021-08-26T21:15:23.690 回答