繁体   English   中英

(python)解析xml文件,但元素以\\结尾

[英](python) parsing xml file but the elements ends with \

晚上好,我必须处理一个xml文件,问题是文件中的元素以不同于通常的格式结尾,例如:

<1ELEMENT>文本<\\ 1ELEMENT>

我使用函数root=etree.parse('filepath') ,并且通过在编译器中手动更改文本中的\\ in /,该函数可以正常工作。 最大的问题是我需要使替换过程自动化,而我想到的唯一解决方案是将文件作为数组导入,将replace /替换为\\并生成一个新的xml文件;但是似乎有点笨拙。 总结我需要知道是否存在一个函数来替换我上面提到的使用root=etree.parse('filepath')的术语。

根据[w3]:可扩展标记语言(XML)1.0(第五版) ,您的XML格式不正确:

为了说明这一点,我准备了一个XML示例,其中包含上述2个项目符号的所有(4)组合(每个项目都可以打开 / 关闭 )。

malformed.xml

<?xml version="1.0" encoding="UTF-8" ?>
<root>
    <1ELEMENT0> text 1ELEMENT0 <\1ELEMENT0>
    <ELEMENT0> text ELEMENT0 <\ELEMENT0>
    <11ELEMENT1> text 11ELEMENT1 </11ELEMENT1>
    <ELEMENT1> text ELEMENT1 </ELEMENT1>
</root>

可以很容易地看出,只有最后一个节点是正确的,并且如果第一个 3个节点中的任何一个存在且未注释 ,则etree会引发ParseError

code.py

import re
from xml.etree import ElementTree as ET


FILE_NAME_0 = "malformed.xml"
FILE_NAME_1 = "wellformed.xml"

END_TAG_BSLASH_PAT = re.compile("<(\\\\).+>")
TAG_DIGIT_PAT = re.compile("</{0,1}(\d+)[^>]+>")


def parse_xml(file_name):
    tree = ET.parse(file_name)
    root_node = tree.getroot()
    for child_node in list(root_node):
        print("{:s} - [{:s}]".format(child_node.tag, child_node.text))


def _process_match(match):
    text = match.group()
    digits_text = match.group(1)
    idx = text.find(digits_text)
    return "_".join([text[:idx], text[idx:]])


def convert_xml_file(in_file_name=FILE_NAME_0, out_file_name=FILE_NAME_1):
    with open(in_file_name) as fin:
        text = fin.read()
        end_tag_bslash_text = re.sub(END_TAG_BSLASH_PAT, lambda x: x.group().replace(x.group(1), "/", 1), text)
        #print(end_tag_bslash_text)
        tag_digit_text = re.sub(TAG_DIGIT_PAT, _process_match, end_tag_bslash_text)
        print(tag_digit_text)
        with open(out_file_name, "w") as fout:
            fout.write(tag_digit_text)


def main():
    #parse_xml(FILE_NAME_0)
    convert_xml_file()
    parse_xml(FILE_NAME_1)


if __name__ == "__main__":
    main()

注意事项

  • 尝试通过修复上述2个错误( ),以语法正确的形式转换上述格式错误的XML
  • parse_xml虚拟函数,用于解析XML文件并转储根节点的子代的标记和文本
  • convert_xml_file进行实际转换:
    • 使用[Python]的组合:正则表达式操作和字符串操作
      • 我知道,这有点差,仅使用regexp绝对有可能做到这一点
      • 模式匹配也很差(例如, < (或> )与标签之间可能存在的SPACE ,如果出现这样的空间,将不会处理标签)
      • 它可能替代了更多内容; 它可以在简单的XML上运行 ,但是如果它们趋向于更复杂,则可以替换正版\\ (例如,在CDATA部分中)
    • 首先,它替换结束标记中的\\
    • 然后,在每个以数字开头的标签(开始和结束)之前添加一个_下划线
    • 将结果文本写入另一个文件(稍后使用)
    • 它以文本模式打开文件,这也是一件坏事,因为它们可能具有不同的编码
  • _process_match :辅助函数(由上一版本使用)来纠正以数字开头的标签(因为这有点复杂,并且lambda很难读取)

输出

 (py35x64_test) E:\\Work\\Dev\\StackOverflow\\q048571060>"e:\\Work\\Dev\\VEnvs\\py35x64_test\\Scripts\\python.exe" code.py <?xml version="1.0" encoding="UTF-8" ?> <root> <_1ELEMENT0> text 1ELEMENT0 </_1ELEMENT0> <ELEMENT0> text ELEMENT0 </ELEMENT0> <_11ELEMENT1> text 11ELEMENT1 </_11ELEMENT1> <ELEMENT1> text ELEMENT1 </ELEMENT1> </root> _1ELEMENT0 - [ text 1ELEMENT0 ] ELEMENT0 - [ text ELEMENT0 ] _11ELEMENT1 - [ text 11ELEMENT1 ] ELEMENT1 - [ text ELEMENT1 ] 

最后说明

  • 许多人注意到,这是在处理效果而不是原因,或者是“ 将污垢隐藏在地毯下 ”。 这是( lam )解决方法( gainarie ),仅用于使您了解这一点
  • XML可能包含其他语法错误
  • 即使该文件现在在语法上正确,也可能存在语义错误
  • 继续朝这个方向前进是一个明确的灾难配方。 适当的修复应该在生成XML的任何地方进行 (这只是常识)

这不是XML文件。

考虑到文件格式是垃圾,您确定内容也不是垃圾吗? 我不想使用来自这样一个不可靠来源的数据。

如果要解析此数据,则需要确定其遵循的规则。 如果这些规则与XML规则非常相似,则可能是将其转换为XML,然后解析XML是解决此问题的一种合理方法。 如果没有,您最好从头开始编写解析器。

但是在您这样做之前,请尝试说服对这种胡言乱语负责的人员遵守标准的好处。

你可以

  1. 加载文件
  2. 做替换,例如

    string_containing_modified_data = data_as_string.replace('\\\\>', '/>')

  3. 使用etree.fromstring(string_containing_modified_data)解析xml。

如果可能的话,您应该尝试修复作家,但是我知道您是否没有机会这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM