lxml.etree.tostring() 在 Mac 和 Linux 中的缩进不同

2 投票
2 回答
566 浏览
提问于 2025-04-17 09:28

在Mac和Linux上,Python的lxml.etree.tostring()的缩进方式不一样——在Mac上的缩进似乎是Linux的两倍。这让我单元测试出问题了。

看起来lxml.etree并没有提供设置默认缩进值的选项。

有没有人知道这可能是什么原因呢?

编辑补充代码:

我确定代码是一样的,这些电脑通过github共享代码。

这是测试代码:

    chk = """\
<field>
      <id>7135260</id>
      <name>lastname</name>
      <label>Last Name</label>
      <type/>
    </field>"""

        res = etree.tostring((xml_obj.xpath(xp_str))[0], pretty_print=True)

        self.assertMultiLineEqual(
            chk,
            res.rstrip()
        )

在Linux上这个测试通过了,但在Mac上失败了,出现了这个错误报告:

-       <id>7135260</id>
+             <id>7135260</id>
? ++++++
-       <name>lastname</name>
+             <name>lastname</name>
? ++++++
-       <label>Last Name</label>
+             <label>Last Name</label>
? ++++++
-       <type/>
+             <type/>
? ++++++
-     </field>
+         </field>
? ++++

但是当我把出问题的代码单独拿出来时,它在两个平台上输出是一样的:

data_str    =   """\
<response>
  <fields>
    <field>
      <id>7135259</id>
      <name>firstname</name>
      <label>First Name</label>
      <type/>
    </field>
    <field>
      <id>7135260</id>
      <name>lastname</name>
      <label>Last Name</label>
      <type/>
    </field>
  </fields>
  <status>success</status>
</response>
"""

data_xml    =   etree.fromstring(data_str)

res = etree.tostring(
        (data_xml.xpath('//*[name="lastname"]/name/..'))[0], 
        pretty_print=True)

print res

这样在两个平台上的缩进都是一样的。

所以不管是什么奇怪的情况,问题似乎出在/unittest2上。现在看来这个问题可能不是很好。

进一步编辑:

当我把比较的内容用repr()包裹起来时,我得到了这个:

- '<field>\n      <id>7135260</id>\n      <name>lastname</name>\n      <label>Last Name</label>\n      <type/>\n    </field>'
+ '<field>\n            <id>7135260</id>\n            <name>lastname</name>\n            <label>Last Name</label>\n            <type/>\n        </field>\n        \n'
?           ++++++                        ++++++                                   ++++++                                ++++++             ++++        ++++++++++++

这个输出实际上是一行的。我在第一个加号和问号字符之间插入了换行符。

我在测试输出中搜索了制表符('\t')。我确定我没有插入制表符,我使用的是vi并设置了'expandtab'。

2 个回答

1

你可以写一个叫做assertXMLEqual的方法,这个方法在比较之前会先去掉缩进。你的测试应该关注你测试的函数生成的xml结构是否正确,至于它是怎么被格式化和缩进的,其实并不重要。

2

你在每个情况下使用的 tostring() 的参数是完全相同的吗?你有没有尝试关闭缩进,看看这是否真的是问题所在?

给我们看看你调用 tostring() 的代码。创建一个小的示例树,并展示在每个操作系统上执行 print len(result_of_tostring)repr(result_of_tostring) 的结果。还要告诉我们你是如何把结果传输到另一个系统进行比较的,并展示用于比较的代码。

更新:你的 "chk" 字符串的缩进看起来有点可疑。我建议 lxml 没有问题,而是你在实验中出现了错误,导致了空格的差异。你有没有从代码中去掉所有的 TAB?你确定没有用一个会把 TAB 替换成空格或者反过来的编辑器打开/保存你的代码吗?为什么不使用 repr() 来清楚地显示不相等的字符串是什么呢?

更新 2:在你的 源代码 中搜索 TAB。你显示的 "chk" 源代码大部分行的缩进是 6。

撰写回答