避免在Python中向XML写入<字符

3
我试图将此文本值写入XML标记中,类似于这样:
 <Parameter name="name"><![CDATA[xyzvalue]]></Parameter>

每当我将这个值作为文本设置到这个标签时,它会生成像这样的内容。
<Parameter name="name">&lt;![CDATA[xyzvalue]]&gt;</Parameter>

我尝试避免在代码中使用转义字符
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")

这个问题不同于如何使用ElementTree输出CDATA,因为我在元素创建时遇到了这个问题,而不是在XML创建后再美化/删除。


展示你的代码。 - Alderven
see the updated question - Ahsan Mukhtar
不熟悉你正在使用的库,但你可能需要设置HTML属性而不是文本。 - s3cur3
我尝试使用 .html 文件,但出现了以下错误:AttributeError: 'xml.etree.ElementTree.Element' 对象没有 'html' 属性。 - Ahsan Mukhtar
1个回答

5
如果是我,我会使用lxml的CDATA
然而,如果你想坚持使用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)

谢谢。输出的XML中也有"字符。你可以帮我解决一下吗? - Ahsan Mukhtar
嗨,我在使用它时遇到了这个错误 TypeError: escape_cdata() 接受的参数数量为1(给定了2个)。 - Ahsan Mukhtar
我正在使用Python 2.7。 - Ahsan Mukhtar
@AhsanMukhtar - 我会尝试在2.7版本中进行复现。我上面的代码是在3.7版本中测试过的。 - Daniel Haley
谢谢!让我试试,然后我会告诉你。 - Ahsan Mukhtar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接