从基于 xml 的文件中提取 N 个字符串

Extract N strings from an xml based file

我目前正在使用 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 中寻找以下内容,并将同一 xml 文件中的 N 个服务器添加到同一行,如下所示:

path,address,port,protocol

例如。来自片段:

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

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

XML 没有很好地嵌套(我原以为 PrivateInsightServerListGroupInfo 的子代),我们需要一些技巧。没关系。

首先,用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 的变量,您还可以使用 "sibling" XPath,例如 -v //GroupInfo/@Path 但这可能无法可靠地工作,就像我说的 XML 对我来说 "nice" 没有出现。)

因为你也用 awk 标记了这个,我假设你有一个最近的 gawkgawkextlib 与 XML 模块(不是你不能简单地做到这一点 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"])
}

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

运行 和 gawk -f parse.awk input.xml("recent" 我的意思是 gawk-4.1 或更高版本)

根据 XML 架构和数据排序,我预计这两种方法都可能会出现问题。