首页 > 解决方案 > 从基于 xml 的文件中提取 N 个字符串

问题描述

我目前正在使用 awk 从基于 xml 的文件中提取多个字符串,并以 csv 格式导出这些字符串

下面是我要获取的标签片段:

    <GroupInfo Description="" Name="Site 2" Path="My Company\Site 2"/>
    ...
    ...
    <PrivateInsightServerList EnableEntireServerList="1" >
      <PrivateInsightServer Address="douda" LegacyClientSupport="1" Port="80" Protocol="HTTP"/>
    </PrivateInsightServerList>
    <PrivateInsightServerList EnableEntireServerList="1" >
      <PrivateInsightServer Address="douda2" LegacyClientSupport="0" Port="443" Protocol="HTTPS"/>
    </PrivateInsightServerList>

我不知道如何解析文件,知道来自 xml 的服务器数量可以从 0 到 N 不等,但总是具有相同的结构。

理想情况下,我在 csv 中查找以下内容,并将 N 个服务器从同一个 xml 文件添加到同一行,如下所示:

path,address,port,protocol

例如。从片段:

My company\site 2,douda,80,HTTP,douda2,443,HTTPS

标签: xmlawkdata-extractionxmlstarlet

解决方案


由于它是必需的,而您没有提供它,我假设您的根 XML 元素只是“ <root>”。

XML 没有很好地嵌套(我本来希望PrivateInsightServerList是 的子级GroupInfo),我们需要一些技巧。不管。

首先,与xmlstarlet

xml sel -t -m '/root/GroupInfo' --var groupinfo=@Path \
  -m '/root/PrivateInsightServerList[@EnableEntireServerList=1]' \
    -v '$groupinfo' -o "," \
    -v PrivateInsightServer/@Address -o "," \
    -v PrivateInsightServer/@Port -o "," \
    -v PrivateInsightServer/@Protocol -nl \
  input.xml
  • -m '/root/GroupInfo' --var groupinfo=@Path 这会将 Path 属性存储在变量中以供以后使用
  • -m '/root/PrivateInsightServerList[@EnableEntireServerList=1]'EnableEntireServerList限制在不为 1的情况下选择的节点
  • 每个-v ... -o ","输出我们想要的值,后跟换行符(-nl

(除了要缓存的变量,Path您还可以使用“兄弟”XPath, -v //GroupInfo/@Path但它可能无法可靠地工作,就像我说的那样,XML 对我来说并不“好”。)

既然你也用 标记了这个awk,我假设你有一个最近的gawkgawkextlibXML 模块(并不是说你不能简单地做到这一点awk,但是如果学习 XML 解析不是任务,那么它不是很有效率手)。

@load "xml"

XMLSTARTELEM &&
  XMLPATH~/GroupInfo$/ { mypath=XMLATTR["Path"] }
XMLSTARTELEM &&
  XMLPATH~/PrivateInsightServerList$/ { ok=XMLATTR["EnableEntireServerList"] }
XMLSTARTELEM &&
   XMLPATH~/PrivateInsightServerList[/]PrivateInsightServer/ {
     if(ok==1) printf("%s,%s,%s,%s\n",
               mypath,XMLATTR["Address"],XMLATTR["Port"],XMLATTR["Protocol"])
}

这有点原始(我还没有使用过 DOMxmltree模块),上面有三个块,每个块都触发XMLSTARTELEM并检查XMLPATH包含元素的完整 XPath。前两个块缓存Pathand EnableEntireServerList,最后一个块根据需要打印出 CSV。

运行gawk -f parse.awk input.xml(“最近”是指 gawk-4.1 或更高版本)

我希望根据 XML 模式和数据顺序,这两种方法都可能存在问题。


推荐阅读