Python lxml 库在空标签中包含 None
Python lxml library includes None in empty tags
正如 mzjn 所建议的那样,我正在更改整个问题并尝试简化它。
我有这个XML:
<Content Version="1.0" Name="Cont">
<Element Ref="Text_4158" ElementType="ItISSomething" GroupName="Some_Content">
<body>
<p>Some content is here.</p>
</body>
</Element>
<Element Ref="List_585" ElementType="ListElements" GroupName="Lists">
<body>
<p><span class="bold">A list of things</span>: Element1, element2, element3, element4 element5.</p>
</body>
</Element>
</Content>
我想修改列表的内容,将“,”替换为“<,>”。我有这个代码:
from lxml import etree as et
def replace_commas(file):
parser = et.parse(str(file))
root = parser.getroot()
xpath_expr = "//Element[starts-with(@Ref,'List_') \
or @GroupName='Lists']/descendant::*"
elements = root.xpath(xpath_expr)
for element in elements:
if element.text is not None or element.tail is not None:
text = str(element.text)
text = text.replace(',', '<,>')
tail = str(element.tail)
tail = tail.replace(',','<,>')
element.text = text
element.tail = tail
tree = et.ElementTree(root)
tree.write(file, pretty_print=True)
预期的输出应该是:
<Content Version="1.0" Name="Cont">
<Element Ref="Text_4158" ElementType="ItISSomething" GroupName="Some_Content">
<body>
<p>Some content is here.</p>
</body>
</Element>
<Element Ref="List_585" ElementType="ListElements" GroupName="Lists">
<body>
<p><span class="bold">A list of things</span>: Element1<,> element2<,> element3<,> element4 element5.</p>
</body>
</Element>
</Content>
然而我的结果是:
<Content Version="1.0" Name="Cont">
<Element Ref="Text_4158" ElementType="ItISSomething" GroupName="Some_Content">
<body>
<p>Some content is here.</p>
</body>
</Element>
<Element Ref="List_585" ElementType="ListElements" GroupName="Lists">
<body>
<p>None<span class="bold">A list of things</span>: Element1<,> element2<,> element3<,> element4 element5.</p>
</body>
</Element>
</Content>
在标签 "p" 和 "span" 之间得到一个 None 并且应该没有任何内容。怎么了?
我希望这个问题的更新有助于理解查询并找到解决方案。
更新: 更正了 def replace_commas(file): 中的冒号和 et.ElementTree(root) 的缩进。
此外,我发现 mzjn 建议的解决方案哪里出错了。我的 xml 这个元素中有:
<Element Ref="List_222"ElementType="ListElements" GroupName="Lists">
<body>
<p><span class="bold">List: <span class="italic">Important elements</span></span>: El1 (prop1), el2 (prop2), el3 (prop3); with a special property.</p>
</body>
</Element>
在这个元素中,我在重要元素的尾部输入 NoneType,因为它的值是 None。
我不知道如何解决它。
如果一个元素的 text
属性 为空(没有值),它 returns 内置常量 None
.
第二个 <p>
元素的 text
属性 为空。但是您使用 text = str(element.text)
,这使得 text
变量等于字符串 'None'
。这就是您在输出中看到的内容。
如果您分别检查每个元素的 text
和 tail
,它应该有效:
for element in elements:
if element.text is not None:
element.text = element.text.replace(',', '<,>')
if element.tail is not None:
element.tail = element.tail.replace(',', '<,>')
看了之后终于找到了解决空尾的办法。我没有检查元素是否为空,而是解决了检查 None 是否不执行任何操作,而是继续。:
for element in elements:
if element.text is None:
continue
else:
element.text = element.text.replace(',','<,>')
if element.tail is None:
continue
else:
element.tail = element.tail.replace(',','<,>')
tree = et.ElementTree(root)
tree.write(args.file, pretty_print=True)
通过此修复,我已经能够解决问题。
正如 mzjn 所建议的那样,我正在更改整个问题并尝试简化它。
我有这个XML:
<Content Version="1.0" Name="Cont">
<Element Ref="Text_4158" ElementType="ItISSomething" GroupName="Some_Content">
<body>
<p>Some content is here.</p>
</body>
</Element>
<Element Ref="List_585" ElementType="ListElements" GroupName="Lists">
<body>
<p><span class="bold">A list of things</span>: Element1, element2, element3, element4 element5.</p>
</body>
</Element>
</Content>
我想修改列表的内容,将“,”替换为“<,>”。我有这个代码:
from lxml import etree as et
def replace_commas(file):
parser = et.parse(str(file))
root = parser.getroot()
xpath_expr = "//Element[starts-with(@Ref,'List_') \
or @GroupName='Lists']/descendant::*"
elements = root.xpath(xpath_expr)
for element in elements:
if element.text is not None or element.tail is not None:
text = str(element.text)
text = text.replace(',', '<,>')
tail = str(element.tail)
tail = tail.replace(',','<,>')
element.text = text
element.tail = tail
tree = et.ElementTree(root)
tree.write(file, pretty_print=True)
预期的输出应该是:
<Content Version="1.0" Name="Cont">
<Element Ref="Text_4158" ElementType="ItISSomething" GroupName="Some_Content">
<body>
<p>Some content is here.</p>
</body>
</Element>
<Element Ref="List_585" ElementType="ListElements" GroupName="Lists">
<body>
<p><span class="bold">A list of things</span>: Element1<,> element2<,> element3<,> element4 element5.</p>
</body>
</Element>
</Content>
然而我的结果是:
<Content Version="1.0" Name="Cont">
<Element Ref="Text_4158" ElementType="ItISSomething" GroupName="Some_Content">
<body>
<p>Some content is here.</p>
</body>
</Element>
<Element Ref="List_585" ElementType="ListElements" GroupName="Lists">
<body>
<p>None<span class="bold">A list of things</span>: Element1<,> element2<,> element3<,> element4 element5.</p>
</body>
</Element>
</Content>
在标签 "p" 和 "span" 之间得到一个 None 并且应该没有任何内容。怎么了?
我希望这个问题的更新有助于理解查询并找到解决方案。
更新: 更正了 def replace_commas(file): 中的冒号和 et.ElementTree(root) 的缩进。
此外,我发现 mzjn 建议的解决方案哪里出错了。我的 xml 这个元素中有:
<Element Ref="List_222"ElementType="ListElements" GroupName="Lists">
<body>
<p><span class="bold">List: <span class="italic">Important elements</span></span>: El1 (prop1), el2 (prop2), el3 (prop3); with a special property.</p>
</body>
</Element>
在这个元素中,我在重要元素的尾部输入 NoneType,因为它的值是 None。
我不知道如何解决它。
如果一个元素的 text
属性 为空(没有值),它 returns 内置常量 None
.
第二个 <p>
元素的 text
属性 为空。但是您使用 text = str(element.text)
,这使得 text
变量等于字符串 'None'
。这就是您在输出中看到的内容。
如果您分别检查每个元素的 text
和 tail
,它应该有效:
for element in elements:
if element.text is not None:
element.text = element.text.replace(',', '<,>')
if element.tail is not None:
element.tail = element.tail.replace(',', '<,>')
看了之后终于找到了解决空尾的办法。我没有检查元素是否为空,而是解决了检查 None 是否不执行任何操作,而是继续。:
for element in elements:
if element.text is None:
continue
else:
element.text = element.text.replace(',','<,>')
if element.tail is None:
continue
else:
element.tail = element.tail.replace(',','<,>')
tree = et.ElementTree(root)
tree.write(args.file, pretty_print=True)
通过此修复,我已经能够解决问题。