如何在XML中输出非转义元素标记?

时间:2015-04-15 15:01:44

标签: python xml html-entities python-2.5

我有一个我继承的Python脚本,我的问题是现在我在paragraph变量中包含一个包含锚标记的文本块。例如:

This is text with a <a href="http://somewebsite.com">Link</a> in it.

我需要做的是将锚标记转换为apxh名称空间,以便上面的行看起来像这样:

This is text with a <apxh:a href="http://somewebsite.com">Link</apxh:a> in it.

问题在于我上面输出的方式是:

This is text with a &lt;apxh:a href=\"http://somewebsite.com;\"&gt;Link Text;&lt;/apxh:a&gt; in it.

我的猜测是,当我在paragraph上运行for循环时,我需要一些如何查找所有锚标签和文本并执行etree.Element("{%s}a" % nm["apxh"], nsmap=nm)之类的操作,但我不太确定

这是当前的脚本:

def get_news_feed(request):
    articles = models.Article.objects.all().filter(distributable = True)

    nm = {
            None: "http://www.w3.org/2005/Atom",
            "ap": "http://ap.org/schemas/03/2005/aptypes",
            "apcm": "http://ap.org/schemas/03/2005/apcm",
            "apnm": "http://ap.org/schemas/03/2005/apnm",
            "apxh": "http://www.w3.org/1999/xhtml",
            }

    doc = etree.Element("{%s}feed" % nm[None], nsmap=nm)

    for article in articles:
        entry = etree.Element("{%s}entry" % nm[None], nsmap=nm)
        content = etree.Element("{%s}content" % nm[None], nsmap=nm)
        content.set("type", "xhtml")

        div = etree.Element("{%s}div" % nm["apxh"], nsmap=nm)
        for paragraph in article.body.replace("&amp;", "&").split("\n"):
            par = etree.Element("{%s}p" % nm["apxh"], nsmap=nm)
            par.text = paragraph            
            par.text = paragraph.replace("<a", "<apxh:a")            
            par.text = par.text.replace("</a", "</apxh:a")  
            par.text = cleanup_entities(par.text)
            div.append(par)
        content.append(div)
        entry.append(content)

        doc.append(entry)

    output = etree.tostring(doc, encoding="UTF-8", xml_declaration=True, pretty_print=True)
    return HttpResponse(output, mimetype="application/xhtml+xml")

这是输出的外观:

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns:ap="http://ap.org/schemas/03/2005/aptypes" xmlns:apxh="http://www.w3.org/1999/xhtml" xmlns:apnm="http://ap.org/schemas/03/2005/apnm" xmlns:apcm="http://ap.org/schemas/03/2005/apcm" xmlns="http://www.w3.org/2005/Atom">
  <entry>
    <content type="xhtml">
      <apxh:div>
        <apxh:p>This is some text</apxh:p>
        <apxh:p>This is text with a <apxh:a href="http://somewebsite.com">Link</apxh:a> in it.</apxh:p>
        <apxh:p>Theater</apxh:p>
      </apxh:div>
    </content>
  </entry>
</feed>

这是目前输出的显示方式:

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns:ap="http://ap.org/schemas/03/2005/aptypes" xmlns:apxh="http://www.w3.org/1999/xhtml" xmlns:apnm="http://ap.org/schemas/03/2005/apnm" xmlns:apcm="http://ap.org/schemas/03/2005/apcm" xmlns="http://www.w3.org/2005/Atom">
  <entry>
    <content type="xhtml">
      <apxh:div>
        <apxh:p>This is some text</apxh:p>
        <apxh:p>This is text with a &lt;apxh:a href=\"http://somewebsite.com;\"&gt;Link Text;&lt;/apxh:a&gt; in it.</apxh:p>
        <apxh:p>Theater</apxh:p>
      </apxh:div>
    </content>
  </entry>
</feed>

1 个答案:

答案 0 :(得分:1)

不要将内容作为文字文本注入 - 将其呈现为DOM内容,使用名称空间映射隐式地使默认名称空间与映射到aphx的名称空间相同:

import lxml.etree as etree
text='This is text with a <a href="http://somewebsite.com">Link</a> in it.'
text_el = etree.fromstring('<root xmlns="http://www.w3.org/1999/xhtml">' + text + '</root>')

...然后将text_el的内容放入par

这样做可能如下所示:

par = etree.Element('{http://www.w3.org/1999/xhtml}div', nsmap=nm)
par.text = text_el.text
for child_el in text_el[:]:
  par.append(child_el)

由于上面使用了nsmap nm,将其转换回字符串将遵循其中包含的名称空间前缀,因此使用apxh表示默认名称空间中保留的内容(我们使用{{{ 1}}在人工根里面。)


在评论的讨论中,您的一些生产数据看起来像是:

xmlns=

u'John Doe: 360-555-4546; <a href=\\"mailto:john.doe@website.com;\\">John.mailto:john.doe@website.com</a> twitter.com/JohnDoe' 在给出此输入时会抛出异常,因为它是反斜杠的无效XML(或有效的XHTML)。

如果您确定在有效输入中不会出现etree.fromstring(),您可能会考虑:

\"