【问题标题】:Python: Extract HTML from an XML filePython:从 XML 文件中提取 HTML
【发布时间】:2009-11-30 02:28:44
【问题描述】:

我的 XML 文件如下所示:

 <strings>
      <string>Bla <b>One &amp; Two</b> Foo</string>
 </strings>

我想在保留内部标签的同时提取每个 的内容。也就是说,我希望看到以下 Python 字符串:u"Bla One & Two Foo"。或者,我想我可以选择 u"Bla One & Two Foo",然后尝试自己替换实体。

我目前正在使用 lxml,它允许我遍历嵌套标签,错过不在标签内的文本,或者遍历所有文本内容 (itertext),从而丢失标签信息。我可能错过了什么。

如果可能的话,我更愿意保留 lxml,但如果需要我可以切换到另一个库。

【问题讨论】:

    标签: python html xml lxml


    【解决方案1】:

    可能有更好的方法来有条件地处理 xpath() 函数返回的对象,但我对 lxml 的了解不够,无法知道它是什么,所以我不得不编写一个函数来返回文本值的一个节点。但话虽如此,这显示了解决问题的一般方法:

    >>> from lxml import etree
    >>> from StringIO import StringIO
    >>> def node_text(n):
            try:
                return etree.tostring(n, method='html', with_tail=False)
            except TypeError:
                return str(n)
    
    >>> f = StringIO('<strings><string>This is <b>not</b> how I plan to escape.</string></strings>')
    >>> x = etree.parse(f)
    >>> ''.join(node_text(n) for n in x.xpath('/strings/string/node()'))
    'This is <b>not</b> how I plan to escape.'
    

    【讨论】:

    • 事实证明,除了使用 node(),还可以使用 child.iterdescendants(),但感谢您为我指明了正确的方向。
    【解决方案2】:

    试试etree.tostring

    outer = etree.tostring(string_elem, method='html')
    inner = re.match("^[^>]+>(.*)<[^<]+$", outer).groups(1)[0]
    

    【讨论】:

    • 我实际上知道tostring,但这包括字符串标签本身。
    • 手动修剪并不难,一个简单的正则表达式就可以了
    • +1 用于发现使用正则表达式处理 XML 并不是一个糟糕的想法的罕见情况之一。
    • 谢谢大家。我想去掉周围的标签也可以很好地工作。
    【解决方案3】:

    不管是什么语言,相对简单的 XSLT 模板都可以解决问题。

    例如为您想要保留的标签定义模式,转换为其他文本。

    您当然可以使用具有兼容 DOM 实现的递归函数(也许是 minidom?)并手动处理标签。

    (伪代码)

    def Function(tag):
       if tag.NodeType = "#text": return tag.innerText
       text=""
       if tag.ElementName in allowedTags:
           text="<%s>"%tag.ElementName
       text += [Function(subtag) for subtag in tag.childs]
       if tag.ElementName in allowedTags:
           text+="</%s>"%tag.ElementName
       return text
    

    【讨论】:

      【解决方案4】:

      不使用解析器,而只是纯粹的字符串操作

      mystring="""
       <strings>
            <string>Bla <b>One &amp; Two</b> Foo</string>
       </strings>
      """
      for s in mystring.split("</string>"):
          if "<string>" in s:
              i = s.index("<string>")
              print s[i+len("<string>"):].replace("&amp;","")
      

      【讨论】:

      • 这个方法的错误列表并不短:其中,如果有一个空的 &lt;string/&gt; 元素,或者如果任何 &lt;string&gt; 元素包含属性,或者其开头的空格或结束标记,或者任何文本节点包含字符实体或 CDATA。
      • 你假设太多了!!。这是一个坏习惯。
      猜你喜欢
      • 1970-01-01
      • 2019-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-24
      相关资源
      最近更新 更多