Как удалить все теги XML, соответствующие tagName и атрибуту в python - PullRequest
0 голосов
/ 30 сентября 2019

У меня большой плоский xsd-файл, в котором перед каждым тегом стоит «xs: Something». Я скомпилировал список неиспользуемых типов в моем сглаженном XML, и мне нужен автоматический способ удаления открывающих, закрывающих тегов и всего, что между ними.

Пример XSD:

<!--W3C XML Schema generated by XMLSpy v2019 rel. 3 sp1 (x64) (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.opentravel.org/OTA/2003/05" targetNamespace="http://www.opentravel.org/OTA/2003/05" elementFormDefault="qualified">
    <xs:annotation>
        <xs:documentation xml:lang="en">All Schema files in the OpenTravel Alliance specification are made available according to the terms defined by the OpenTravel License Agreement at http://www.opentravel.org/Specifications/Default.aspx.</xs:documentation>
    </xs:annotation>
    <xs:simpleType name="AvailabilityStatusType">
        <xs:annotation>
            <xs:documentation xml:lang="en">Identifies the availability status of an item.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:NMTOKENS">
            <xs:enumeration value="Open">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Close">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="ClosedOnArrival">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="ClosedOnArrivalOnRequest">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory may not be available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="OnRequest">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory may be available.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="RemoveCloseOnly">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Remove Close restriction while keeping other restrictions in place.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="RatePlanEnum">
        <xs:annotation>
            <xs:documentation xml:lang="en">Identifies rate plan types.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:NMTOKENS">
            <xs:enumeration value="Government">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Negotiated">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Preferred">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Other_">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory may not be available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
        </xs:restriction>
    </xs:simpleType>

Допустим, мой список неиспользуемых типов выглядит следующим образом: myTypes = [RatePlanEnum]

Это означает, что я хочу удалить все имя simpleType =Узел RatePlanEnum.

Я пытался:

from lxml import etree 
doc = etree.parse('myfile.xml') 
for elem in doc.findall('.//xs:simpleType'): 
    parent = elem.getparent() 
    if(elem.attrib.get('name') = 'RatePlanEnum'): 
        parent.remove(elem)

Как мне сделать это программно и выплюнуть xml после всех модификаций?

Ответы [ 2 ]

1 голос
/ 01 октября 2019

Этот файл использует пространство имен xmlns:xs="http://www.w3.org/2001/XMLSchema", и вы должны использовать {http://www.w3.org/2001/XMLSchema} вместо xs: в findall()

 doc.findall('.//{http://www.w3.org/2001/XMLSchema}simpleType'):

Doc: lxml - Пространства имен


Полный пример:

from lxml import etree 

data = '''<!--W3C XML Schema generated by XMLSpy v2019 rel. 3 sp1 (x64) (http://www.altova.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.opentravel.org/OTA/2003/05" targetNamespace="http://www.opentravel.org/OTA/2003/05" elementFormDefault="qualified">
    <xs:annotation>
        <xs:documentation xml:lang="en">All Schema files in the OpenTravel Alliance specification are made available according to the terms defined by the OpenTravel License Agreement at http://www.opentravel.org/Specifications/Default.aspx.</xs:documentation>
    </xs:annotation>
    <xs:simpleType name="AvailabilityStatusType">
        <xs:annotation>
            <xs:documentation xml:lang="en">Identifies the availability status of an item.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:NMTOKENS">
            <xs:enumeration value="Open">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Close">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="ClosedOnArrival">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="ClosedOnArrivalOnRequest">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory may not be available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="OnRequest">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory may be available.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="RemoveCloseOnly">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Remove Close restriction while keeping other restrictions in place.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="RatePlanEnum">
        <xs:annotation>
            <xs:documentation xml:lang="en">Identifies rate plan types.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:NMTOKENS">
            <xs:enumeration value="Government">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Negotiated">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Preferred">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory is not available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
            <xs:enumeration value="Other_">
                <xs:annotation>
                    <xs:documentation xml:lang="en">Inventory may not be available for sale to arriving guests.</xs:documentation>
                </xs:annotation>
            </xs:enumeration>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>'''

doc = etree.fromstring(data)

for elem in doc.findall('.//{http://www.w3.org/2001/XMLSchema}simpleType'):
    parent = elem.getparent()
    if elem.attrib.get('name') == 'RatePlanEnum':
        parent.remove(elem)

print(etree.tostring(doc).decode())
0 голосов
/ 01 октября 2019

Используя lxml, вы можете применить таблицу стилей XSLT-1.0, которая игнорирует элемент, который должен быть удален при передаче параметра в таблицу стилей. Остальная часть файла копируется с помощью идентификационного шаблона , а ненужные пробелы удаляются xsl:strip-space.

Здесь параметр передается remov (= RatePlanEnum):

remov = ET.XSLT.strparam('RatePlanEnum')  

Таблица стилей XSLT-1.0 (remove.xslt):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
    <xsl:strip-space elements="*" />
    <xsl:param name="toRemove" />

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="xs:simpleType">
        <xsl:if test="@name != $toRemove">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*" />
            </xsl:copy>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

Код Python для вызова этой таблицы стилей может быть:

import lxml.etree as ET

# Parse XML and XSLT
dom = ET.parse(input_xml_filename)
xslt = ET.parse('remove.xslt')
transform = ET.XSLT(xslt)
# Set the parameter which specifies the element to be removed
remov = ET.XSLT.strparam('RatePlanEnum')
result = transform(dom, toRemove=remov)

# Print the result
print(ET.tostring(result, pretty_print=True))
...