Прошу помощи в автоматизации редактирования файла *.xml
Здравствуйте уважаемые участники сообщества!
Передо мной стоит задача в уменьшении файла безопасности OVAL с целью оптимизации проверки и уменьшении нагрузки на серверные мощности. Он имеет формат xml, внушительный размер 164Mb и довольно понятную структуру, сейчас я постараюсь всё подробно описать.
<defenitions>
<definition id="oval:org.opensuse.security:def:19990524"....>
.....
</defenition>
</defenitions>
<tests>
<rpminfo_test id="oval:org.opensuse.security:tst:2009334017" ..... >
.....
</rpminfo_test>
</tests>
<object>
<rpminfo_object id="oval:org.opensuse.security:obj:2009030416" ..... >
.....
</rpminfo_object>
</object>
<states>
<rpminfo_state id="oval:org.opensuse.security:ste:2009079458" ... >
.....
</rpminfo_state>
</states>
Так вот нужно найти блоки в которых XXXXXXXX меньше определённого значения и удалить полностью его содержимое, вместе с тегами.
Вот например в блоке < defenitions> содержится огромное количество подблоков < defenition> каждый со своим id. И если его id меньше 20170000, то его нужно удалить полностью и повторить операцию со следующим блоком. А в блоке < tests> и в следующих двух поисковым числом должно быть 2017000000.
Помогите написать скрипт на python, использоваться он будет на SUSE Linux Enterprise
Небольшой кусочек файла до запуска скрипта
<?xml version="1.0" encoding="UTF-8"?>
<oval_definitions
xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux "
xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
xmlns:oval-def="http://oval.mitre.org/XMLSchema/oval-definitions-5">
<generator>
<oval:product_name>Marcus Updateinfo to OVAL Converter</oval:product_name>
<oval:schema_version>5.5</oval:schema_version>
<oval:timestamp>2022-04-27T06:04:52</oval:timestamp>
</generator>
<definitions>
<definition id="oval:org.opensuse.security:def:19990524" version="1" class="vulnerability">
<metadata>
<title>CVE-1999-0524</title>
#Дальше идёт много строчек текста/кода обрезал их из-за большого количества символов
</metadata>
</definition>
<definition id="oval:org.opensuse.security:def:20001254" version="1" class="vulnerability">
<metadata>
<title>CVE-2000-1254</title>
#Дальше идёт много строчек текста/кода обрезал их из-за большого количества символов
</metadata>
</definition>
<definition id="oval:org.opensuse.security:def:20170405" version="1" class="vulnerability">
<metadata>
<title>CVE-2017-0405</title>
#Дальше идёт много строчек текста/кода обрезал их из-за большого количества символов
</metadata>
</definition>
</definitions>
<tests>
<rpminfo_test id="oval:org.opensuse.security:tst:2009334017" version="1" comment="kernel-default is ==0" check="all" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<object object_ref="oval:org.opensuse.security:obj:2009030416"/>
<state state_ref="oval:org.opensuse.security:ste:2009079458"/>
</rpminfo_test>
<rpminfo_test id="oval:org.opensuse.security:tst:2017669873" version="1" comment="sled-release is ==15" check="at least one" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<object object_ref="oval:org.opensuse.security:obj:2017031917"/>
<state state_ref="oval:org.opensuse.security:ste:2017061809"/>
</rpminfo_test>
</tests>
<objects>
<rpminfo_object id="oval:org.opensuse.security:obj:2009030416" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<name>kernel-default</name>
</rpminfo_object>
<rpminfo_object id="oval:org.opensuse.security:obj:2017030418" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<name>kernel-source</name>
</rpminfo_object>
</objects>
<states>
<rpminfo_state id="oval:org.opensuse.security:ste:2009079458" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="equals">0</version>
</rpminfo_state>
<rpminfo_state id="oval:org.opensuse.security:ste:2017061809" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="equals">15</version>
</rpminfo_state>
</states>
</oval_definitions>
А вот это я хочу видеть после отрабатывания скрипта
<?xml version="1.0" encoding="UTF-8"?>
<oval_definitions
xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux "
xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
xmlns:oval-def="http://oval.mitre.org/XMLSchema/oval-definitions-5">
<generator>
<oval:product_name>Marcus Updateinfo to OVAL Converter</oval:product_name>
<oval:schema_version>5.5</oval:schema_version>
<oval:timestamp>2022-04-27T06:04:52</oval:timestamp>
</generator>
<definitions>
<definition id="oval:org.opensuse.security:def:20170405" version="1" class="vulnerability">
<metadata>
<title>CVE-2017-0405</title>
#Дальше идёт много строчек текста/кода обрезал их из-за большого количества символов
</metadata>
</definition>
</definitions>
<tests>
<rpminfo_test id="oval:org.opensuse.security:tst:2017669873" version="1" comment="sled-release is ==15" check="at least one" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<object object_ref="oval:org.opensuse.security:obj:2017031917"/>
<state state_ref="oval:org.opensuse.security:ste:2017061809"/>
</rpminfo_test>
</tests>
<objects>
<rpminfo_object id="oval:org.opensuse.security:obj:2017030418" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<name>kernel-source</name>
</rpminfo_object>
</objects>
<states>
<rpminfo_state id="oval:org.opensuse.security:ste:2017061809" version="1" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux">
<version operation="equals">15</version>
</rpminfo_state>
</states>
</oval_definitions>
Как уже видно не осталось блоков с id меньше 2017000000
Ответы (1 шт):
Пожалуйста, попробуйте следующий XSLT.
Оно использует так называемый Identity Transform шаблон.
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:oval-def="http://oval.mitre.org/XMLSchema/oval-definitions-5"
xmlns:ns2="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux" xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5">
<xsl:output method="xml" omit-xml-declaration="no" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--delete not needed elements based on the trailing @id value-->
<xsl:template match="oval-def:definition[number(substring(@id,32,8)) < 20170000]" />
<xsl:template match="ns2:rpminfo_test[number(substring(@id,32,10)) < 2017000000]" />
<xsl:template match="ns2:rpminfo_object[number(substring(@id,32,10)) < 2017000000]" />
<xsl:template match="ns2:rpminfo_state[number(substring(@id,32,10)) < 2017000000]" />
</xsl:stylesheet>
Python
import os
import lxml.etree as ET
import sys
if sys.version_info[0] >= 3:
unicode = str
inputfile = "D:\\temp\\input.xml"
xsltfile = "D:\\temp\\process.xslt"
outfile = "D:\\output\\output.xml"
dom = ET.parse(inputfile)
xslt = ET.parse(xsltfile)
transform = ET.XSLT(xslt)
newdom = transform(dom)
infile = unicode((ET.tostring(newdom, pretty_print=True)))
outfile = open(outfile, 'a')
outfile.write(infile)