选择父级和子级属性值

时间:2018-10-12 11:25:12

标签: xml parsing xpath

我有一个如下所示的xml文件:

<tag>
   <file name="name1">
      <error message="error1"/>
      <error message="error2"/>
   </file>
   <file name="name2">
      <error message="error1"/>
      <error message="error2"/>
   </file>
</tag>

我希望得到下一个结果:

name1: error1, error1;
name2: error1, error1

我正在尝试做这样的事情:

*//file/@name | //file/error/@message*

但是,这当然是行不通的。我可以实施地图吗?

2 个答案:

答案 0 :(得分:1)

使用XPath 3.1,

string-join(/tag/file ! (@name || ': ' || string-join(error/@message, ', ')), '#')

其中#表示根据宿主语言的约定转义的换行符,例如\n用于Java,&#xa;用于XSLT。

对于XPath 2.0,将A!B替换为for $a in A return B,并将A||B替换为concat(A, B)

XPath 1.0:如果没有宿主语言支持,则不可能。

答案 1 :(得分:0)

这仅适用于XPath-2.0或更高版本。您可以使用以下表达式创建一个字符串作为结果。它使用适当的定界符,和LF &#xa;

for $nam in /tag/file/@name, $msg in $nam/../error return concat(if (generate-id($msg) = generate-id($nam/../error[1])) then concat($nam,': ',$msg/@message) else $msg/@message, if (generate-id($msg) = generate-id($nam/../error[last()])) then ';&#xa;' else ',')

输出为:

name1: error1, error2;
name2: error1, error2;

此输出与上面所需的输出(error2而不是error1)和结尾的;略有不同。如果您需要摆脱最后一个;,可以通过实现与换行一样的原理来实现。

P.S .:检查第一个和最后一个元素的方法似乎不是最优的,因此可能还有改进的空间。