在xslt中,xpath配置命名空间
文章目录
问题简要
最近在尝试折腾opds相关的东西,将opds转为特定格式的html并由rclone挂载,但是遇到了一个命名空间相关的问题,opds使用的xml格式设置了一个命名空间,导致无法正常使用xpath解析opds原始文件,在此就尝试解决的内容进行记录。
命名空间简述
xml的命名空间是用于避免多个xml发生冲突的方法。
其在xml中使用 xmlns
以类似于属性的方式进行规定。可以在xmlns关键字后面加上冒号以规定名称空间简写,如果没有简写,则在该xml子树中视为默认命名空间(没特别声明的标签将会归类至该标签中)
该xmlns允许主动声明为空值,表示归类在空 命名空间。也就是未主动声明命名空间的情况下所属的命名空间。
|
|
比如说上面这个xml中,和标签属于’http://www.w3.org/TR/html4/'命名空间下,而dc:test标签属于’http://purl.org/dc/terms/'命名空间下。而以及里面的子树则被归类在了空命名空间。
类似于这样,允许一个xml中使用多个命名空间。能够方便配置,以及避免冲突……?
纯xpath匹配(通常很麻烦)
假设一个xml如下,并使用了一个默认命名空间
|
|
这样一个xml不能使用 /feed/test
来匹配,因为feed位于一个另外的命名空间,这时可以用 /*['feed'=local-name()]
来忽略命名空间强行匹配,不过,需要注意的是,此处命名空间设置,不会递归传递到后面,因此,如果需要多层嵌套的话,会非常麻烦。 /*['feed'=local-name()]/*['test'=local-name()]
而且,也有可能(极小概率的)导致出现命名空间冲突(毕竟命名空间本来就是用来规避冲突的嘛)。
而在xpath2.0版本中,以上语法也能记作 “\*:foo"来忽略命名空间匹配本地名称,不过,该新版标准并不太普及(至少截至本文,xnllint并不支持该语法),如果不支持则还需要记作 [local-name() = 'foo']
。
在xslt中设置命名空间前戳
如果只是需要在xslt中使用xpath匹配其他xml的命名空间的话,则可以考虑将对应的命名空间对应一个前戳来使用。
只需要在xsl:stylesheet标签中将对应的xmlns:前戳的属性加上去即可。
|
|
类似于这样,在该xsl文件中,可以直接使用 ’\/atom:标签/‘ 这样的xpath来匹配属于’http://www.w3.org/2005/Atom'命名空间的标签。能够大幅度简化xpath的配置,并提高xpath的准确性。(毕竟 ['标签'=local-name()]
这样的xpath,是直接忽略掉命名空间进行匹配的呢)
链接记录,参考文章
https://www.w3school.com.cn/xml/xml%5Fnamespaces.asp
https://www.cnblogs.com/bmaker/p/5605738.html
https://hustlei.github.io/2015/05/xml-xsl-xpath-namespace.html
文章作者 crimsonote
上次更新 2021-11-23