Избегайте записи <символов в XML в python - PullRequest
1 голос
/ 13 марта 2019

Я пытаюсь записать это текстовое значение в тег XML следующим образом:

 <Parameter name="name"><![CDATA[xyzvalue]]></Parameter>

Всякий раз, когда я устанавливаю это значение как текст для этого тега.Он генерирует это так:

<Parameter name="name">&lt;![CDATA[xyzvalue]]&gt;</Parameter>

Мне нужно было попытаться избежать символов unescape в коде

ET.SubElement(parameters, "Parameter", name="id").text = unescape("&lt;![CDATA[xyzvalue]]>")

Как я могу избежать записи этого в файл XML?Мне нужно избегать экранирования символов в XML.

Это мой полный код:

map = ET.Element("Map")

parameters = ET.SubElement(map, "Parameters")
ET.SubElement(parameters, "Parameter", name="bounds").text = "-180,-85.05112877980659,180,85.05112877980659"
ET.SubElement(parameters, "Parameter", name="center").text = "0,0,2"
ET.SubElement(parameters, "Parameter", name="format").text = "png"
ET.SubElement(parameters, "Parameter", name="minzoom").text = "0"
ET.SubElement(parameters, "Parameter", name="maxzoom").text = "22"
ET.SubElement(parameters, "Parameter", name="scale").text = "1"
ET.SubElement(parameters, "Parameter", name="metatile").text = "2"
ET.SubElement(parameters, "Parameter", name="id").text = unescape("&lt;![CDATA[xyzvalue]]>")
ET.SubElement(parameters, "Parameter", name="_updated").text = "1552288036000"
ET.SubElement(parameters, "Parameter", name="name").text = "<![CDATA[xyzvalue]]>"
ET.SubElement(parameters, "Parameter", name="tilejson").text = "<![CDATA[2.0.0]]>"
ET.SubElement(parameters, "Parameter", name="scheme").text = "<![CDATA[xyz]]>"

indent(map)
tree = ET.ElementTree(map)
tree.write("plotfinder_tiles.xml", xml_declaration=True, encoding='utf-8', method="xml")

Это отличается от Как вывести CDATA с помощью ElementTree в некотором смысле, что у меня есть эта проблема при создании элемента, чтобы не prettify / удалить после создания XML.

1 Ответ

1 голос
/ 13 марта 2019

Если бы это был я, я бы использовал lxml's CDATA class .

Однако, если вы хотите придерживаться ElementTree, вы могли бы , вероятно, переопределить ET._escape_cdata и убедиться, что текст не начинается с <![CDATA[ и не заканчивается ]]> перед выходом.

Пример ...

Python 3. #

import xml.etree.ElementTree as ET


def escape_cdata(text):
    # escape character data
    try:
        if not text.startswith("<![CDATA[") and not text.endswith("]]>"):
            if "&" in text:
                text = text.replace("&", "&amp;")
            if "<" in text:
                text = text.replace("<", "&lt;")
            if ">" in text:
                text = text.replace(">", "&gt;")
        return text
    except (TypeError, AttributeError):
        ET._raise_serialization_error(text)


ET._escape_cdata = escape_cdata

map_elem = ET.Element("Map")

parameters = ET.SubElement(map_elem, "Parameters")
ET.SubElement(parameters, "Parameter", name="bounds").text = "-180,-85.05112877980659,180,85.05112877980659"
ET.SubElement(parameters, "Parameter", name="center").text = "0,0,2"
ET.SubElement(parameters, "Parameter", name="format").text = "png"
ET.SubElement(parameters, "Parameter", name="minzoom").text = "0"
ET.SubElement(parameters, "Parameter", name="maxzoom").text = "22"
ET.SubElement(parameters, "Parameter", name="scale").text = "1"
ET.SubElement(parameters, "Parameter", name="metatile").text = "2"
ET.SubElement(parameters, "Parameter", name="id").text = "<![CDATA[xyzvalue]]>"
ET.SubElement(parameters, "Parameter", name="_updated").text = "1552288036000"
ET.SubElement(parameters, "Parameter", name="name").text = "<![CDATA[xyzvalue]]>"
ET.SubElement(parameters, "Parameter", name="tilejson").text = "<![CDATA[2.0.0]]>"
ET.SubElement(parameters, "Parameter", name="scheme").text = "<![CDATA[xyz]]>"

tree = ET.ElementTree(map_elem)
tree.write("test.xml", xml_declaration=True, encoding='utf-8', method="xml")

Вывод XML (test.xml; довольно печатный для удобства чтения)

<Map>
    <Parameters>
        <Parameter name="bounds">-180,-85.05112877980659,180,85.05112877980659</Parameter>
        <Parameter name="center">0,0,2</Parameter>
        <Parameter name="format">png</Parameter>
        <Parameter name="minzoom">0</Parameter>
        <Parameter name="maxzoom">22</Parameter>
        <Parameter name="scale">1</Parameter>
        <Parameter name="metatile">2</Parameter>
        <Parameter name="id"><![CDATA[xyzvalue]]></Parameter>
        <Parameter name="_updated">1552288036000</Parameter>
        <Parameter name="name"><![CDATA[xyzvalue]]></Parameter>
        <Parameter name="tilejson"><![CDATA[2.0.0]]></Parameter>
        <Parameter name="scheme"><![CDATA[xyz]]></Parameter>
    </Parameters>
</Map>

Обновление: функция для Python 2.7

def escape_cdata(text, encoding):
    # escape character data
    try:
        if not text.startswith("<![CDATA[") and not text.endswith("]]>"):
            if "&" in text:
                text = text.replace("&", "&amp;")
            if "<" in text:
                text = text.replace("<", "&lt;")
            if ">" in text:
                text = text.replace(">", "&gt;")
        return text.encode(encoding, "xmlcharrefreplace")
    except (TypeError, AttributeError):
        ET._raise_serialization_error(text)
...