使用xmlstarlet

时间:2018-05-01 16:04:39

标签: xml xpath xmlstarlet

我有一些XML(例如,文件 minimal.xml ),其中包含以下格式的错误和警告消息:

<?xml version="1.0" encoding="UTF-8"?>
  <messages>
     <message subMessage="RSC-004">RSC-004, ERROR, [File 'OEBPS/Text/pdfMigration.html' could not be decrypted.], epub20_encryption_binary_content.epub</message>
     <message subMessage="RSC-012">RSC-012, ERROR, [Fragment identifier is not defined.], OEBPS/toc.ncx (24-67)</message>
     <message subMessage="RSC-012">RSC-012, ERROR, [Fragment identifier is not defined.], OEBPS/toc.ncx (30-82)</message>
     <message subMessage="RSC-012">RSC-012, ERROR, [Fragment identifier is not defined.], OEBPS/toc.ncx (36-81)</message>
     <message subMessage="RSC-012">RSC-012, ERROR, [Fragment identifier is not defined.], OEBPS/toc.ncx (42-75)</message>
     <message subMessage="RSC-012">RSC-012, ERROR, [Fragment identifier is not defined.], OEBPS/toc.ncx (48-61)</message>
     <message subMessage="HTM-023">HTM-023, WARN, [An invalid XHTML Named Entity was found: '&amp;0;'.], OEBPS/Text/pdfMigration.html (18-199)</message>
     <message subMessage="HTM-023">HTM-023, WARN, [An invalid XHTML Named Entity was found: '&amp;l0xb'.], OEBPS/Text/pdfMigration.html (291-6)</message>
  </messages>

我正在寻找一种方法来提取代表ERROR的所有消息元素的 subMessage 属性值(可以通过ERROR中的ERROR来识别) message 元素的文本值)。我正在使用xmlstarlet。经过一番搜索,我发现this somewhat similar case,所以我改编如下:

xmlstarlet sel -t -v '/messages[contains(message,"ERROR")]/message/@subMessage' minimal.xml

结果:

RSC-004
RSC-012
RSC-012
RSC-012
RSC-012
RSC-012
HTM-023
HTM-023

这不是我的预期,因为这些是所有消息元素的 subMessage 值!作为进一步的测试,我修改了查询以仅提取警告:

xmlstarlet sel -t -v '/messages[contains(message,"WARN")]/message/@subMessage' minimal.xml

在这种情况下,结果是空的!我对xmlstarlet很新,我怀疑我在这里忽略了一些明显的东西。任何帮助非常感谢!

BTW关于我正在使用的xmlstarlet版本的一些信息:

  

针对libxml2 2.9.2编译,与20903链接   根据libxslt 1.1.28编译,与10128链接

2 个答案:

答案 0 :(得分:1)

试试这个

xmlstarlet sel -t -v '/messages/message[contains(.,"ERROR")]/@subMessage' minimal.xml

使用/messages[contains(message,"WARN")],您错误地尝试检查messages元素的内容,而不是每个message元素的内容。

答案 1 :(得分:1)

您需要将谓词移动到message,如下所示:

xmlstarlet sel -t -v "/messages/message[contains(.,'WARN')]/@subMessage" minimal.xml