python 如何防止lxml将“&”字符转换为“&”?

bwntbbo3  于 2023-02-11  发布在  Python
关注(0)|答案(2)|浏览(237)

我需要在XML文件中发送控制字符
,以便在目标系统中正确显示文本。
为了创建XML文件,我使用了lxml库,下面是我的尝试:

from lxml import etree as et
import lxml.builder

e = lxml.builder.ElementMaker()

xml_doc = e.newOrderRequest(
    e.Orders(
        e.Order(
            e.OrderNumber('12345'),
            e.OrderID('001'),
            e.Articles(
                e.Article(
                    e.ArticleNumber('000111'),
                    e.ArticleName('Logitec Mouse'),
                    e.ArticleDescription('* 4 Buttons
* 600 DPI
* Bluetooth')
                )
            )
        )
    )
)

tree = et.ElementTree(xml_doc)
tree.write('output.xml', pretty_print=True, xml_declaration=True, encoding="utf-8")

这就是结果:

<?xml version='1.0' encoding='UTF-8'?>
<newOrderRequest>
  <Orders>
    <Order>
      <OrderNumber>12345</OrderNumber>
      <OrderID>001</OrderID>
      <Articles>
        <Article>
          <ArticleNumber>000111</ArticleNumber>
          <ArticleName>Logitec Mouse</ArticleName>
          <ArticleDescription>* 4 Buttons&amp;#x0D;&amp;#x0A;* 600 DPI&amp;#x0D;&amp;#x0A;* Bluetooth</ArticleDescription>
        </Article>
      </Articles>
    </Order>
  </Orders>
</newOrderRequest>

这就是我需要的

<ArticleDescription>* 4 Buttons&#x0D;&#x0A;* 600 DPI&#x0D;&#x0A;* Bluetooth</ArticleDescription>

lxml库中有没有函数可以关闭转换或者有没有人知道解决这个问题的方法?提前感谢。

idfiyjo8

idfiyjo81#

这不是python或lxml的问题,而是XML解析器和序列化器的工作方式。如果您想在编程语言中使用特定字符,那么就使用该字符。如果需要,序列化器会将其转换为实体引用,解析器会在阅读文档时将其转换回来。您不能关闭它,因为这将违反规范。
请参见https://www.w3.org/TR/REC-xml/#syntax:“与”符号(&)和左尖括号(〈)不得以其文字形式出现,除非用作标记分隔符,或在注解、处理指令或CDATA节中使用。如果在其他地方需要它们,则必须分别使用数字字符引用或字符串“&amp;“和“&lt;“对其进行转义。
使用CDATA节可能是一个例外,如What does in XML mean?中所述

t40tm48m

t40tm48m2#

Python脚本的输出:

import lxml.etree as et
print(repr(et.fromstring('''<ArticleDescription>* 4 Buttons&#x0D;&#x0A;* 600 DPI&#x0D;&#x0A;* Bluetooth</ArticleDescription>''').text))

是...

'* 4 Buttons\r\n* 600 DPI\r\n* Bluetooth'

这意味着Python语法编写XML语法字符串* 4 Buttons&#x0D;&#x0A;* 600 DPI&#x0D;&#x0A;* Bluetooth的方式是'* 4 Buttons\r\n* 600 DPI\r\n* Bluetooth'
因此,相关代码行应为:

e.ArticleDescription('* 4 Buttons\r\n* 600 DPI\r\n* Bluetooth')

......如果消费者不将结果输出视为 * 与 * import lxml.etree as et print(repr(et.fromstring('''<ArticleDescription>* 4 Buttons&#x0D;&#x0A;* 600 DPI&#x0D;&#x0A;* Bluetooth</ArticleDescription>完全相同,则该消费者被破坏。
请参阅https://replit.com/@CharlesDuffy2/ImportantClassicConversion#test.py,运行带有上述建议修改的代码。

相关问题