多次提取并删除第一次出现的 XML 标记

多次提取并删除第一次出现的 XML 标记

我有一个尺寸不大的 XML 文件。我已经获得了这些信息,我所需要做的就是提取 XML 标记之间的一些值。因为XML我的机器上没有可用的解析器实用程序。我正在寻找替代方法。

首先,有一个<capacity> </capacity重复的 XML 标签 >nXML 文件中的时间数以及此 XML 标记之间还有许多其他不同的标记。

我必须<capacity> </capacity>分别获取每个出现的 XML 标记,然后对其进行解析并提取它们下的值。

<subcolumns><capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
</subcolumns>

因此,我认为的逻辑是找到第一次出现的<capacity> </capacity>XML 标记并将其打印到临时文件,然后删除第一次出现的位置。

<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

此后,当第二次执行此操作时,<capacity> </capacity>将考虑新的 XML 标记对。所以这必须重复多次,直到<capacity> </capacity>找到最后一个标签。每次提取这部分数据都会发生变化并且可以提取。

<capacity> </capacity>现在我想要的只是从主 XML 文件中选择第一次出现的XML 标记并将其打印到临时文件并删除该部分。

这就是我尝试过的,但没有任何效果。

sed -n '2,${/<capacity>\(.*\)<\/capacity>/\1/p;q;}' "<input XML file>" >> temp.txt

我进一步的想法是获取该临时文件进行处理并提取标签下所需的值capacity。我已经为此编写了逻辑并且运行良好。

答案1

使用 XML 解析器是操作 XML 文档的正确方法。

xmlstarlet解决方案:

xmlstarlet sel -t -c '//capacity[1]' -n yourxml > temp.txt 
&& xmlstarlet ed -d '//capacity[1]' yourxml > tmp.xml && mv tmp.xml yourxml 

cat temp.txt
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

  • xmlstarlet sel -t -c '//capacity[1]' -n yourxml > temp.txt- 提取第一个capacity标签声明并将输出重定向到temp.txt

  • xmlstarlet ed -d '//capacity[1]' yourxml > tmp.xmlcapacity-从文档中删除第一个标签(通过-d删除操作)并将修改后的文档内容重定向到临时文件tmp.xml

  • mv tmp.xml yourxml- 用修改后的版本替换初始 xml 文档

答案2

由于您没有 xml 解析器,请使用 gnu awk 尝试一下:

$ awk -v RS="<subcolumns>|</capacity>" 'NR==2{gsub(/^\n/,"");print $0 RT;exit}' file.xml
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

为什么这样有效:
在 awk 中,您可以设置自定义记录/行分隔符。在我们的示例中,我们使用<subcolumns></capacity>

因此,通过自定义记录分隔符,我们可以实现以下格式:

$ awk -v RS="<subcolumns>|</capacity>" '{gsub(/^\n/,"");print NR,$0 RT}' file.xml
1 <subcolumns>
2 <capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
3 <capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
4 <capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
5 </subcolumns>

PS:NR = 数字或记录/行。 RT=使用的记录分隔符。

因此,您可以<capacity></capacity>通过调整 NR 编号来打印任何块:

$ awk -v RS="<subcolumns>|</capacity>" 'NR==4{gsub(/^\n/,"");print $0 RT}'
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

因此,如果您需要跳过一个<capacity>部分(即第一个容量部分),您可以执行以下操作:

$ awk -v RS="<subcolumns>|</capacity>" '{gsub(/^\n/,"")}NR!=2{print $0 RT}'
<subcolumns>
<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
</subcolumns>

答案3

chunk=2; # specify the tag chunk number here which must be > 0
perl -l -0777ne "print((m{(<capacity>.*?</capacity>)}sg)[${chunk:-1}-1])" yourxmlfile

结果

<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>

相关内容