从基于 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 没有很好地嵌套(我原以为 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
的变量,您还可以使用 "sibling" XPath,例如
-v //GroupInfo/@Path
但这可能无法可靠地工作,就像我说的 XML 对我来说 "nice" 没有出现。)
因为你也用 awk
标记了这个,我假设你有一个最近的 gawk
和 gawkextlib
与 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。前两个块缓存 Path
和 EnableEntireServerList
,最后一个块根据需要打印出 CSV。
运行 和 gawk -f parse.awk input.xml
("recent" 我的意思是 gawk-4.1 或更高版本)
根据 XML 架构和数据排序,我预计这两种方法都可能会出现问题。
我目前正在使用 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 没有很好地嵌套(我原以为 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
的变量,您还可以使用 "sibling" XPath,例如
-v //GroupInfo/@Path
但这可能无法可靠地工作,就像我说的 XML 对我来说 "nice" 没有出现。)
因为你也用 awk
标记了这个,我假设你有一个最近的 gawk
和 gawkextlib
与 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。前两个块缓存 Path
和 EnableEntireServerList
,最后一个块根据需要打印出 CSV。
运行 和 gawk -f parse.awk input.xml
("recent" 我的意思是 gawk-4.1 或更高版本)
根据 XML 架构和数据排序,我预计这两种方法都可能会出现问题。