严格来说,我对自己的问题有一个答案,但要以我喜欢的方式实际实施它还需要更多的工作。以下是操作方法。
创建 XMLFormatter 的子类(或 HTMLFormatter,如果您使用 HTML),将其命名为您想要的名称。我选择了“排序属性”。编写函数“attributes”,以便它按照您想要的顺序返回一个元组列表:[(attribute1, value1), (attribute2, value2), etc.]。我的可能看起来很冗长,但我这样做是因为我使用非常不一致的 XML。
from bs4 import BeautifulSoup
from bs4.formatter import XMLFormatter
class SortAttributes(XMLFormatter):
def attributes(self, tag):
"""Reorder a tag's attributes however you want."""
attrib_order = ['id', 'head', 'postag', 'relation', 'form', 'lemma']
new_order = []
for element in attrib_order:
if element in tag.attrs:
new_order.append((element, tag[element]))
for pair in tag.attrs.items():
if pair not in new_order:
new_order.append(pair)
return new_order
xml_string = '''
<word form="συ" head="2610" id="2357" lemma="συ" postag="p-s----n-" relation="ExD_AP"/>
'''
soup = BeautifulSoup(xml_string, 'xml')
print(soup.encode(formatter=SortAttributes()))
这将输出我想要的:
<word id="2357" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
很方便,我可以使用相同的编码方法对整个文档执行此操作。但是,如果我将其作为字符串写入文件,则所有标签都将首尾相连。示例如下:
<sentence id="783"><word id="2357" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/><word id="2358" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/><word id="2359" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/></sentence>
而不是我更喜欢的东西:
<sentence id="783">
<word id="2357" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
<word id="2358" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
<word id="2359" head="2610" postag="p-s----n-" relation="ExD_AP" form="συ" lemma="συ"/>
</sentence>
要解决这个问题,我不能只是 .prettify 它,因为 prettify 会将属性重新排列回字母顺序。我将不得不详细介绍 XMLFormatter 子类。我希望将来有人会发现这对您有所帮助!