BeautifulSoup通过原始xml替换标记而无需解析/转义

时间:2016-02-11 00:39:32

标签: python xml xml-parsing beautifulsoup

假设我有这样的xml(真正的那个更复杂):

<a>
    <b>
        <c replace="alpha" />
    </b>
    <d>
        <c replace="beta"></c>
    </d>
</a>

我使用BeautifulSoup(lxml)解析了这个,因为我can't use regex。现在我用包含新的有效xml的字符串替换<c>,该字符串取决于属性。这并不是那么难。

但是我想在不使用BeautifulSoup解析新的xml的情况下这样做。原因是我只是想在之后美化它。有相当多的标签被大量的xml取代。它不是非常高效的解析,然后美化一切。

是否有类似LiteralXmlPleaseDontParseThisTnx节点的内容? (我找不到它,他们必须把它称为别的东西,并且'raw html','unparsed html','literal hmtl'......太多无关的点击。)。

或者,有没有办法对上面的xml进行美化处理,然后将新的xml作为纯文本插入(没有假设xml超出有效范围)?

2 个答案:

答案 0 :(得分:2)

BeautifulSoup用于解析HTML。你所拥有的不是HTML,而是XML,所以你可能不应该使用BeautifulSoup,而是直接使用lxml。

lxml元素确实有replace方法,但您必须传递一个元素,而不是字符串。我们不清楚你要用<c>代替什么,但如果你从一开始就把你的替换值作为元素创建,你可以在不解析的情况下进行替换。

相反,如果您只是想删除一个任意字符串来代替<c>,那么,这对XML文档来说不是一个格式良好的操作,而且库不可能可以保证你粘贴的内容是格式良好的,因此不可能将给定的结果序列化。大多数XML库都会特别禁止该操作,因为它会违反XML库试图维护的基本假设和保证。

答案 1 :(得分:0)

我找到了一种创建相同结果的方法,这对我来说很有用,但可能并不普遍适用。它位于&#39;或者&#39;问题类别:在解析汤之外做替换。

  • 在解析主文档之前转义字符串格式化大括号:

    escaped = sub(r'({|})', r'\1\1', input)
    soup = BeautifulSoup(escaped, 'lxml')  # or lxml
    
  • 用替换字符串替换<c replace="alpha" />(对于所有这些字符串):

    name = c_tag.attrs['replace']
    ctag.replace_with(NavigableString('{' + name + ':s}'))
    
  • 将所有替换品存储在字典中(可能已经是这种情况):

    rep = {'alpha': '<lots /><of-xml />', 'beta': '<b>hi</b>'}
    
  • 使用字符串格式进行所有替换:

    output = soup.prettify().format(**rep)
    

我承认我的案子有点特别,所以也许它对许多其他人没有帮助。但在我的情况下,每个<c>可以被包含更多<c> s的xml替换。由于多进程通信,每个级别都需要进行解析或pickle。 (酸洗比解析快20-50%,并且遇到硬递归限制)。所以必须只执行一次而不是每个级别,这节省了我很多时间(在我测试的情况下因子3),因为正则表达式替换和字符串替换比解析快得多。