使用 python 解析 xml(查找具有特定文本的标签)
Parsing xml with python (find tags with specific text)
我的任务是处理一个 xml 文件,以查找特定元素并将它们导出到 csv 文件中..
我在处理相同标签中的一些信息时遇到了问题:
<name>text</name>
<value>value</value>
每个名称标签包含不同的值,我只需要其中的一些..
我尝试使用以下代码遍历文件:
try:
descr = member.find('.//name').text
if descr == 'description':
plugin.append(descr)
except AttributeError:
descr = 'Unknown'
plugin.append(descr)
但它只是 returns 'Unknown'
我的整个代码是这样的(未完成):
import xml.etree.ElementTree as ET
import csv
tree = ET.parse('plugins.xml')
root = tree.getroot()
nessus_out = open('/home/rj/Documents/python/nessus_out.csv', 'w')
csvwriter = csv.writer(nessus_out)
for member in root.findall('nasl'):
plugin = []
id = member.find('script_id').text
plugin.append(id)
name = member.find('script_name').text
plugin.append(name)
family = member.find('script_family').text
plugin.append(family)
#for each in member.iterfind('nasl'):
try:
solution = member.xpath('.//name/text()')
if solution == 'solution':
plugin.append(solution)
except AttributeError:
solution = 'Unknown'
plugin.append(solution)
csvwriter.writerow(plugin)
nessus_out.close()
最终目标是搜索 "solution" 并从其标签中获取相应的值。
xml结构如下:
nasl_plugins
nasl_plugins/nasl
nasl_plugins/nasl/filename
nasl_plugins/nasl/script_id
nasl_plugins/nasl/script_name
nasl_plugins/nasl/script_family
nasl_plugins/nasl/attributes/attribute/name
nasl_plugins/nasl/attributes/attribute/value
丹尼尔:
Xml 片段:
<nasl>
<filename>fedora_2017-c3149b5fcb.nasl</filename>
<script_id>101028</script_id>
<script_name>Fedora 25 : xen (2017-c3149b5fcb)</script_name>
<script_version>$Revision: 1.5 $</script_version>
<script_copyright>This script is Copyright (C) 2017-2018 Tenable Network Security, Inc.</script_copyright>
<script_family>Fedora Local Security Checks</script_family>
<cves>
<cve>CVE-2017-10911</cve>
<cve>CVE-2017-10912</cve>
<cve>CVE-2017-10913</cve>
<cve>CVE-2017-10915</cve>
<cve>CVE-2017-10916</cve>
<cve>CVE-2017-10917</cve>
<cve>CVE-2017-10918</cve>
<cve>CVE-2017-10919</cve>
<cve>CVE-2017-10920</cve>
<cve>CVE-2017-10923</cve>
</cves>
<bids>
</bids>
<xrefs>
<xref>FEDORA:2017-c3149b5fcb</xref>
<xref>IAVB:2017-B-0074</xref>
</xrefs>
<dependencies>
<dependency>ssh_get_info.nasl</dependency>
</dependencies>
<required_keys>
<key>Host/local_checks_enabled</key>
<key>Host/RedHat/release</key>
<key>Host/RedHat/rpm-list</key>
</required_keys>
<attribute>
<name>plugin_type</name>
<value>local</value>
</attribute>
<attribute>
<name>plugin_modification_date</name>
<value>2018/02/02</value>
</attribute>
<attribute>
<name>stig_severity</name>
<value>I</value>
</attribute>
<attribute>
<name>cvss_base_score</name>
<value>10.0</value>
</attribute>
</attributes>
我要寻找的是 stig_severity、base_cvss_score 和其他一些值。所以我的推理是搜索 ,它们向下移动一行并获得值。至于 csv,我需要它在一行 pr 中。插件,所以采用这种格式:
id,name,family,solution,description,synopsis,base_cvss_score,plugin_type,stig_severity
然后是下一行下一个插件的值..
看起来你想要的一些值是 nasl
的直接子值,一些在 attributes/attribute
.
中
您可以做的是有两个列表(或元组);一种具有准确的元素名称,另一种具有准确的属性名称 (attribute/name
)。
注意:这可能听起来有点令人困惑,因为在这种情况下 "attribute name" 实际上是一个名为 "attribute" 的元素和一个名为 "name" 的子元素,而不是真正的 XML 名为 "name".
的属性
组合这些元组将为您提供 CSV 中的所有字段。您可以使用它来构建一个包含默认值为 Unknown
.
的所有字段的字典
然后您可以迭代这两个元组来构建您的两种不同类型的 XPath。如果该元素存在,则在字典中更新文本值。否则该值保持 Unknown
.
示例...
XML 输入 (test.xml)
<nasl_plugins>
<nasl>
<filename>fedora_2017-c3149b5fcb.nasl</filename>
<script_id>101028</script_id>
<script_name>Fedora 25 : xen (2017-c3149b5fcb)</script_name>
<script_version>$Revision: 1.5 $</script_version>
<script_copyright>This script is Copyright (C) 2017-2018 Tenable Network Security,
Inc.</script_copyright>
<script_family>Fedora Local Security Checks</script_family>
<cves>
<cve>CVE-2017-10911</cve>
<cve>CVE-2017-10912</cve>
<cve>CVE-2017-10913</cve>
<cve>CVE-2017-10915</cve>
<cve>CVE-2017-10916</cve>
<cve>CVE-2017-10917</cve>
<cve>CVE-2017-10918</cve>
<cve>CVE-2017-10919</cve>
<cve>CVE-2017-10920</cve>
<cve>CVE-2017-10923</cve>
</cves>
<bids> </bids>
<xrefs>
<xref>FEDORA:2017-c3149b5fcb</xref>
<xref>IAVB:2017-B-0074</xref>
</xrefs>
<dependencies>
<dependency>ssh_get_info.nasl</dependency>
</dependencies>
<required_keys>
<key>Host/local_checks_enabled</key>
<key>Host/RedHat/release</key>
<key>Host/RedHat/rpm-list</key>
</required_keys>
<attributes>
<attribute>
<name>plugin_type</name>
<value>local</value>
</attribute>
<attribute>
<name>plugin_modification_date</name>
<value>2018/02/02</value>
</attribute>
<attribute>
<name>stig_severity</name>
<value>I</value>
</attribute>
<attribute>
<name>cvss_base_score</name>
<value>10.0</value>
</attribute>
</attributes>
</nasl>
</nasl_plugins>
Python 3.x
import csv
from lxml import etree
elem_names = ('script_id', 'script_name', 'script_family')
attr_names = ('solution', 'description', 'synopsis', 'cvss_base_score', 'plugin_type',
'stig_severity')
field_names = elem_names + attr_names
with open('test.csv', 'w', newline='', encoding='utf8') as xml_data_to_csv:
csv_writer = csv.DictWriter(xml_data_to_csv, fieldnames=field_names,
quoting=csv.QUOTE_ALL)
csv_writer.writeheader()
tree = etree.parse('test.xml')
for nasl in tree.xpath('.//nasl'):
# Build a dict containing all of the "field_names" with default values of "Unknown".
values = {key: 'Unknown' for key in field_names}
# Process the direct children of "nasl".
for elem_name in elem_names:
for child in nasl.xpath(f'*[self::{elem_name}]'):
values[child.tag] = child.text
# Process attribute with matching attribute names.
for attr_name in attr_names:
for val in nasl.xpath(f'attributes/attribute[name="{attr_name}"]/value'):
values[attr_name] = val.text
csv_writer.writerow(values)
输出 (test.csv)
"script_id","script_name","script_family","solution","description","synopsis","cvss_base_score","plugin_type","stig_severity"
"101028","Fedora 25 : xen (2017-c3149b5fcb)","Fedora Local Security Checks","Unknown","Unknown","Unknown","10.0","local","I"
我的任务是处理一个 xml 文件,以查找特定元素并将它们导出到 csv 文件中..
我在处理相同标签中的一些信息时遇到了问题:
<name>text</name>
<value>value</value>
每个名称标签包含不同的值,我只需要其中的一些.. 我尝试使用以下代码遍历文件:
try:
descr = member.find('.//name').text
if descr == 'description':
plugin.append(descr)
except AttributeError:
descr = 'Unknown'
plugin.append(descr)
但它只是 returns 'Unknown'
我的整个代码是这样的(未完成):
import xml.etree.ElementTree as ET
import csv
tree = ET.parse('plugins.xml')
root = tree.getroot()
nessus_out = open('/home/rj/Documents/python/nessus_out.csv', 'w')
csvwriter = csv.writer(nessus_out)
for member in root.findall('nasl'):
plugin = []
id = member.find('script_id').text
plugin.append(id)
name = member.find('script_name').text
plugin.append(name)
family = member.find('script_family').text
plugin.append(family)
#for each in member.iterfind('nasl'):
try:
solution = member.xpath('.//name/text()')
if solution == 'solution':
plugin.append(solution)
except AttributeError:
solution = 'Unknown'
plugin.append(solution)
csvwriter.writerow(plugin)
nessus_out.close()
最终目标是搜索 "solution" 并从其标签中获取相应的值。
xml结构如下:
nasl_plugins
nasl_plugins/nasl
nasl_plugins/nasl/filename
nasl_plugins/nasl/script_id
nasl_plugins/nasl/script_name
nasl_plugins/nasl/script_family
nasl_plugins/nasl/attributes/attribute/name
nasl_plugins/nasl/attributes/attribute/value
丹尼尔:
Xml 片段:
<nasl>
<filename>fedora_2017-c3149b5fcb.nasl</filename>
<script_id>101028</script_id>
<script_name>Fedora 25 : xen (2017-c3149b5fcb)</script_name>
<script_version>$Revision: 1.5 $</script_version>
<script_copyright>This script is Copyright (C) 2017-2018 Tenable Network Security, Inc.</script_copyright>
<script_family>Fedora Local Security Checks</script_family>
<cves>
<cve>CVE-2017-10911</cve>
<cve>CVE-2017-10912</cve>
<cve>CVE-2017-10913</cve>
<cve>CVE-2017-10915</cve>
<cve>CVE-2017-10916</cve>
<cve>CVE-2017-10917</cve>
<cve>CVE-2017-10918</cve>
<cve>CVE-2017-10919</cve>
<cve>CVE-2017-10920</cve>
<cve>CVE-2017-10923</cve>
</cves>
<bids>
</bids>
<xrefs>
<xref>FEDORA:2017-c3149b5fcb</xref>
<xref>IAVB:2017-B-0074</xref>
</xrefs>
<dependencies>
<dependency>ssh_get_info.nasl</dependency>
</dependencies>
<required_keys>
<key>Host/local_checks_enabled</key>
<key>Host/RedHat/release</key>
<key>Host/RedHat/rpm-list</key>
</required_keys>
<attribute>
<name>plugin_type</name>
<value>local</value>
</attribute>
<attribute>
<name>plugin_modification_date</name>
<value>2018/02/02</value>
</attribute>
<attribute>
<name>stig_severity</name>
<value>I</value>
</attribute>
<attribute>
<name>cvss_base_score</name>
<value>10.0</value>
</attribute>
</attributes>
我要寻找的是 stig_severity、base_cvss_score 和其他一些值。所以我的推理是搜索 ,它们向下移动一行并获得值。至于 csv,我需要它在一行 pr 中。插件,所以采用这种格式:
id,name,family,solution,description,synopsis,base_cvss_score,plugin_type,stig_severity
然后是下一行下一个插件的值..
看起来你想要的一些值是 nasl
的直接子值,一些在 attributes/attribute
.
您可以做的是有两个列表(或元组);一种具有准确的元素名称,另一种具有准确的属性名称 (attribute/name
)。
注意:这可能听起来有点令人困惑,因为在这种情况下 "attribute name" 实际上是一个名为 "attribute" 的元素和一个名为 "name" 的子元素,而不是真正的 XML 名为 "name".
的属性组合这些元组将为您提供 CSV 中的所有字段。您可以使用它来构建一个包含默认值为 Unknown
.
然后您可以迭代这两个元组来构建您的两种不同类型的 XPath。如果该元素存在,则在字典中更新文本值。否则该值保持 Unknown
.
示例...
XML 输入 (test.xml)
<nasl_plugins>
<nasl>
<filename>fedora_2017-c3149b5fcb.nasl</filename>
<script_id>101028</script_id>
<script_name>Fedora 25 : xen (2017-c3149b5fcb)</script_name>
<script_version>$Revision: 1.5 $</script_version>
<script_copyright>This script is Copyright (C) 2017-2018 Tenable Network Security,
Inc.</script_copyright>
<script_family>Fedora Local Security Checks</script_family>
<cves>
<cve>CVE-2017-10911</cve>
<cve>CVE-2017-10912</cve>
<cve>CVE-2017-10913</cve>
<cve>CVE-2017-10915</cve>
<cve>CVE-2017-10916</cve>
<cve>CVE-2017-10917</cve>
<cve>CVE-2017-10918</cve>
<cve>CVE-2017-10919</cve>
<cve>CVE-2017-10920</cve>
<cve>CVE-2017-10923</cve>
</cves>
<bids> </bids>
<xrefs>
<xref>FEDORA:2017-c3149b5fcb</xref>
<xref>IAVB:2017-B-0074</xref>
</xrefs>
<dependencies>
<dependency>ssh_get_info.nasl</dependency>
</dependencies>
<required_keys>
<key>Host/local_checks_enabled</key>
<key>Host/RedHat/release</key>
<key>Host/RedHat/rpm-list</key>
</required_keys>
<attributes>
<attribute>
<name>plugin_type</name>
<value>local</value>
</attribute>
<attribute>
<name>plugin_modification_date</name>
<value>2018/02/02</value>
</attribute>
<attribute>
<name>stig_severity</name>
<value>I</value>
</attribute>
<attribute>
<name>cvss_base_score</name>
<value>10.0</value>
</attribute>
</attributes>
</nasl>
</nasl_plugins>
Python 3.x
import csv
from lxml import etree
elem_names = ('script_id', 'script_name', 'script_family')
attr_names = ('solution', 'description', 'synopsis', 'cvss_base_score', 'plugin_type',
'stig_severity')
field_names = elem_names + attr_names
with open('test.csv', 'w', newline='', encoding='utf8') as xml_data_to_csv:
csv_writer = csv.DictWriter(xml_data_to_csv, fieldnames=field_names,
quoting=csv.QUOTE_ALL)
csv_writer.writeheader()
tree = etree.parse('test.xml')
for nasl in tree.xpath('.//nasl'):
# Build a dict containing all of the "field_names" with default values of "Unknown".
values = {key: 'Unknown' for key in field_names}
# Process the direct children of "nasl".
for elem_name in elem_names:
for child in nasl.xpath(f'*[self::{elem_name}]'):
values[child.tag] = child.text
# Process attribute with matching attribute names.
for attr_name in attr_names:
for val in nasl.xpath(f'attributes/attribute[name="{attr_name}"]/value'):
values[attr_name] = val.text
csv_writer.writerow(values)
输出 (test.csv)
"script_id","script_name","script_family","solution","description","synopsis","cvss_base_score","plugin_type","stig_severity"
"101028","Fedora 25 : xen (2017-c3149b5fcb)","Fedora Local Security Checks","Unknown","Unknown","Unknown","10.0","local","I"