【问题标题】:lxml sourceline returning Nonelxml 源代码行返回无
【发布时间】:2019-06-25 00:40:32
【问题描述】:

使用beautifulsoup和lxml解析时需要获取xml的行号。

xml 缺少根标记,因此无法直接使用 XML 元素树/lxml。所以用beautifulsoup刮掉它。需要在嵌套字典中保留 xml 的文件名、行号、xml 标记及其值。尝试使用 beautifulsoup/lxml 抓取时无法获取行号。 print(linenum) 返回 None 但需要在 xml 文件中返回行号。有什么想法吗?

for xml_file in os.listdir("/Users/abc/Documents/test"):
    mode_map = defaultdict(list)       
    with open("/Users/abc/test/"+xml_file) as raw_resuls:    

        results = BeautifulSoup(raw_resuls, 'lxml')            

        for element in results.find_all("process"):
            attrib = element['mode']                
            if element.find("value") is not None:    
                child = element.find("value").text                    
                linenum= element.find("value").sourceline                    
                print(linenum)                    
                mode_map[attrib].append(child)                    


               # print(mode_map)

        event_map["process"]=mode_map    
        file_map[xml_file]=event_map

【问题讨论】:

  • BeautifulSoup 元素没有名为“sourceline”的属性。您的linenum 变为None 而不是引发AttributeError 的原因是BeautifulSoup 元素还允许您使用element.process 之类的语法而不是element.findChild('process') 按名称查找孩子,其中None 作为故障保护.我个人不喜欢这样:在很多情况下可能很方便,但感觉迟早你会无意中碰到 BeautifulSoup 元素的现有属性。
  • 既然lxml有你想要的特性,而BeautifulSoup没有,那为什么不直接使用lxml呢?如果 xml 的所有问题在于它“缺少根标记”,那么您至少可以自己打一个根标记。

标签: python beautifulsoup lxml


【解决方案1】:

由于我找不到更好的东西,我将其发布为答案。就像你习惯的那样简单地from lxml import etree。然后,这样做:

    with open("/Users/abc/test/"+xml_file) as fin:    
        raw_xml = fin.read()
        results = etree.XML('<root>' + raw_xml + '</root>')

我相信您知道下一步该做什么,因为您似乎对 lxml 很熟悉。由于我添加的&lt;root&gt;...&lt;/root&gt; 标记对不带有换行符,因此它们不会以任何方式影响您的sourceline

【讨论】:

  • 谢谢!字符串连接的想法就像一个魅力。但是,当我尝试解析 etree.XML 时,它抛出了一个错误,所以我查阅了文档,BytesIO 成功了!
【解决方案2】:

这对我有用!

with open("/Users/abc/Documents/test/"+xml_file) as fin:

        raw_xml = fin.read()

        new_xml="<root>" + raw_xml + "</root>"

        some_file_like = BytesIO(new_xml.encode())

        for event, element in etree.iterparse(some_file_like):
            if element.tag == 'process':
                attrib = element.attrib['mode']
                #print(attrib)
                if element.find("value") is not None:

                    child = element.find("value").text
                    linenum= element.find("value").sourceline
                    print(linenum)

【讨论】:

    猜你喜欢
    • 2018-05-03
    • 2017-05-27
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-18
    • 1970-01-01
    相关资源
    最近更新 更多