我有一个如下所示的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*
但是,这当然是行不通的。我可以实施地图吗?
答案 0 :(得分:1)
使用XPath 3.1,
string-join(/tag/file ! (@name || ': ' || string-join(error/@message, ', ')), '#')
其中#表示根据宿主语言的约定转义的换行符,例如\n
用于Java,

用于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 

。
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 ';
' else ',')
输出为:
name1: error1, error2;
name2: error1, error2;
此输出与上面所需的输出(error2
而不是error1
)和结尾的;
略有不同。如果您需要摆脱最后一个;
,可以通过实现与换行一样的原理来实现。
P.S .:检查第一个和最后一个元素的方法似乎不是最优的,因此可能还有改进的空间。