LINUX.ORG.RU

Чистка XML в Python

 , ,


0

2

Имеется страшненький XML, например такой:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <ns1:updateProductDef soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:ProductAdmin">
            <ns1:arg0 xmlns:ns2="ebridge:UserContext" xsi:type="ns2:userContext">
                <DBName xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:string">TheDataTheBase</DBName>
                <ip xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:string">10.10.10.10</ip>
                <name xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:string">iivanov</name>
                <password xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:string">******</password>
            </ns1:arg0>
            <ns1:arg1 xsi:type="ns1:productDef">
                <basecostperunit xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:nil="true" xsi:type="soapenc:double"/>
                <canruntillforbid xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">0</canruntillforbid>
                <companyid xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">207</companyid>
                <defaultzoneid xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:nil="true" xsi:type="soapenc:long"/>
                <groupbuyvieworder xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:nil="true" xsi:type="soapenc:long"/>
                <id xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">121</id>
                <incinpgldump xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:nil="true" xsi:type="soapenc:long"/>
                <iseditorialproduct xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">0</iseditorialproduct>
                <isonlineproduct xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">0</isonlineproduct>
                <productid xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">121</productid>
                <publishfriday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishfriday>
                <publishmonday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishmonday>
                <publishsaturday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishsaturday>
                <publishsunday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishsunday>
                <publishthursday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishthursday>
                <publishtuesday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishtuesday>
                <publishwednesday xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="soapenc:long">1</publishwednesday>
                <unitmeasure xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xsi:nil="true" xsi:type="soapenc:long"/>
            </ns1:arg1>
        </ns1:updateProductDef>
    </soapenv:Body>
</soapenv:Envelope> """

Нужно убрать из него все атрибуты, неймспейсы, а также юзерконтекст и SOAP-конверт. Чтобы получилось что-то вроде


            <arg1>
                <basecostperunit/>
                <canruntillforbid>0</canruntillforbid>
                <companyid  >207</companyid>
                <defaultzoneid/>
                <groupbuyvieworder/>
                <id>121</id>
                <incinpgldump/>
                <iseditorialproduct>0</iseditorialproduct>
                <isonlineproduct>0</isonlineproduct>
                <productid>121</productid>
                <publishfriday>1</publishfriday>
                <publishmonday>1</publishmonday>
                <publishsaturday>1</publishsaturday>
                <publishsunday>1</publishsunday>
                <publishthursday>1</publishthursday>
                <publishtuesday>1</publishtuesday>
                <publishwednesday>1</publishwednesday>
                <unitmeasure/>
            <arg1>

Такой получился случай, когда нужно работать с SOAP-реквестами не только через suds но еще и молотком. По сути, мне нужно удалить все атрибуты и оставить только то, что <arg1>внутри</arg1>. Гуглеж как-то не очень помог. Во всяком случае, я не нашел примера кода, удаляющего все атрибуты из XML. Помоги мне, ЛОР.

Лучше всего для этого использовать lxml

Делается это приблизительно так:

from lxml import etree
src = """<?xml version="1.0" encoding="UTF-8"?>....."""
root = etree.XML(src)
new_root = root.xpath("//ns1:arg1", namespaces={"ns1": "urn:ProductAdmin"})[0]
for elem in new_root.iter():
    # Здесь можно что-то сделать с элементом
    print elem.tag

k0valenk0_igor ★★★
()
Ответ на: комментарий от k0valenk0_igor

Вся беда и заключается в том, что это может быть не «ProductAdmin» а все, что угодно. Или например «ns5:arg1» вместо «ns1:arg1»

horonitel ★★
() автор топика
Ответ на: комментарий от horonitel

Но ведь в SOAP, насколько я понимаю, все пакеты устроены одинаково: <soapenv:Envelope><soapenv:Body>полезное содержимое</soapenv:Body></soapenv:Envelope>, ведь так? Я думаю особого труда не составит написать выражение XPath отсчитывающее два уровня начиная от корня, а потом взять полученную ноду как новый коревой элемент и делать уже с ним все что необходимо.

k0valenk0_igor ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.