我有一系列变量类型,例如:
abc1A, abc1B, abc3B, ...
xyz1A, xyz2A, xyz3C, ...
data1C, data2A, ...
以多种xml格式存储:
<area name="DataMap">
<int name="number" nullable="true">
<case var="abc2,abc3,abc5">11</case>
<case var="abc4,abc6*">8</case>
<case var="data1,xyz7,xyz8">22</case>
<case var="data3A,xyz{9},xyz{5A,5B,5C}">24</case>
<case var="xyz{6,4A,4B,4C}">20</case>
<case var="other01">15</case>
</int>
</area>
我希望查询像 xyz5A 这样的实例映射到什么。查询应该返回 24,但我事先不知道 xml 节点中的引用是否像“xyz4A”中那样显式,或者通过像“xyz4*”这样的通配符,或者像上面那样在大括号中。
这将查询该行上的字符串并将成功返回:
xpath '/area[@name="DataMap"]/int[@name="number"]/case[contains(@var,"xyz")][contains(@var,"5A")]'
但它也返回了 data5A 的命中,这并不是不正确的:
xpath '/area[@name="DataMap"]/int[@name="number"]/case[contains(@var,"data")][contains(@var,"5A")]'
是否有 xpath/其他查询构造可以解析上面不一致的(但我假设有效)xml?我似乎只能查询显式字符串匹配与通配符和大括号格式。
最佳答案
在 bash/perl
中,您可能会绑定(bind)到 libxml
。 libxml 不支持 XPath 2.0。关于 XPath/XSLT 2.0 与 libxml/libxslt 和 Perl 的 SO 有很多问题。
XPath 1.0 有多种(我不得不承认很小的一种)string functions你可以尝试将它们堆叠在一起。我进行了一些实验,但我也不喜欢结果,也没有成功涵盖所有可能的情况。你会有“丑陋”的结构,比如:
...
or
(contains(@var, ',xyz{') and
contains(substring-before(substring-after(@var, ',xyz{'), '}'), '5A') and
(contains(substring-before(substring-after(@var, ',xyz{'), '}'), ',5A,') or
starts-with(substring-after(@var, ',xyz{'), '5A,') or
starts-with(substring-after(@var, ',xyz{'), '5A}') or
substring-after(substring-before(substring-after(@var, ',xyz{'), '}'), ',5A') = ''))
or
...
然后您会意识到 substring-*
函数在第一次出现匹配字符串时起作用,并且您需要更多层 and
和 或
来处理像您这样的情况:
<case var="data3A,xyz{9},xyz{5A,5B,5C}">24</case>
其中存在多个 xyz{
,并且您需要的未知是第一个。
我认为在这种情况下,您会忘记自己有一个 XML,而只是执行 Perl 擅长的操作并将其视为文本。尽管我非常喜欢用于 XML 处理和数据提取的 XML 感知工具,但使用专为其设计的语言中的正则表达式和字符串操作可能会更好。
关于perl - xml 格式变化时的 xpath 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10647147/