2009-10-26 53 views
1

我在使用xml.dom.minidom轉義xml文件中的「<」和「>」時被卡住了。 我試圖讓Unicode的十六進制值並使用它
http://slayeroffice.com/tools/unicode_lookup/使用xml.dom.minidom在xml中轉義'<' and '>'

試圖用標準的「<」和「>」,但仍然沒有成功。

from xml.dom.minidom import Document 
doc = Document() 
e = doc.createElement("abc") 
s1 = '<hello>bhaskar</hello>' 
text = doc.createTextNode(s1) 
e.appendChild(text) 

e.toxml() 
'<abc>&lt;hello&gt;bhaskar&lt;/hello&gt;</abc>' 

與相同中WriteXML結果() 通過在toxml用於()指定中WriteXML編碼 'UTF-8', 'UTF-8', 'UTF'()調用但具有相同的結果也試過。

from xml.dom.minidom import Document 
doc = Document() 
e = doc.createElement("abc") 
s1 = u'&lt;hello&gt;bhaskar&lt;/hello&gt;' 
text = doc.createTextNode(s1) 
e.appendChild(text) 

e.toxml() 
u'<abc>&amp;lt;hello&amp;gt;bhaskar&amp;lt;/hello&amp;gt;</abc>' 

試過其他方法,但結果相同。 只有這樣我可以解決辦法是通過重寫作家

import xml.dom.minidom as md 
# XXX Hack to handle '<' and '>' 
def wd(writer, data): 
    data = data.replace("&lt;", "<").replace("&gt;", ">") 
    writer.write(data) 

md._write_data = wd 

編輯 - 這是代碼

import xml.dom.minidom as md 
    doc = md.Document() 

    entity_descr = doc.createElement("EntityDescriptor") 
    doc.appendChild(entity_descr) 
    entity_descr.setAttribute('xmlns', 'urn:oasis:names:tc:SAML:2.0:metadata') 
    entity_descr.setAttribute('xmlns:saml', 'urn:oasis:names:tc:SAML:2.0:assertion') 
    entity_descr.setAttribute('xmlns:ds', 'http://www.w3.org/2000/09/xmldsig#') 
    # Get the entity_id from saml20_idp_settings 
    entity_descr.setAttribute('entityID', self.group['entity_id']) 

    idpssodescr = doc.createElement('IDPSSODescriptor') 
    idpssodescr.setAttribute('WantAuthnRequestsSigned', 'true') 
    idpssodescr.setAttribute('protocolSupportEnumeration', 
    'urn:oasis:names:tc:SAML:2.0:protocol') 
    entity_descr.appendChild(idpssodescr) 

    keydescr = doc.createElement('KeyDescriptor') 
    keydescr.setAttribute('use', 'signing') 
    idpssodescr.appendChild(keydescr) 
    keyinfo = doc.createElement('ds:KeyInfo') 
    keyinfo.setAttribute('xmlns:ds', 'http://www.w3.org/2000/09/xmldsig#') 
    keydescr.appendChild(keyinfo) 
    x509data = doc.createElement('ds:X509Data') 
    keyinfo.appendChild(x509data) 


    # check this part 

    s = "this is a cert blah blah" 
    x509cert = doc.createElement('ds:X509Certificate') 
    cert = doc.createTextNode(s) 
    x509cert.appendChild(cert) 
    x509data.appendChild(x509cert) 

    sso = doc.createElement('SingleSignOnService') 
    sso.setAttribute('Binding', 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect') 

    sso.setAttribute('Location', 'http://googleapps/singleSignOn') 
    idpssodescr.appendChild(sso) 

    # Write the metadata file. 
    fobj = open('metadata.xml', 'w') 
    doc.writexml(fobj, " ", "", "\n", "UTF-8") 
    fobj.close() 

這將產生

<?xml version="1.0" encoding="UTF-8"?> 
    <EntityDescriptor entityID="skar" xmlns="urn:oasis:names:tc:SAML:2.0:metadata"  
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> 
    <IDPSSODescriptor WantAuthnRequestsSigned="true" 
    protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> 
    <KeyDescriptor use="signing"> 
    <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
    <ds:X509Data> 
    <ds:X509Certificate> 
    this is a cert blah blah 
    </ds:X509Certificate> 
    </ds:X509Data> 
    </ds:KeyInfo> 
    </KeyDescriptor> 
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" 
    Location="http:///singleSignOn"/> 
    </IDPSSODescriptor> 
    </EntityDescriptor> 

注意「這是一個證書」來seperately 有打破我的頭在這一點,但具有相同的結果。

回答

6

這不是一個錯誤,它是一個功能。要插入實際的XML,請改爲插入DOM對象。 XML標籤中的文本需要實體轉義,儘管它是有效的XML。

from xml.dom.minidom import Document 
doc = Document() 
e = doc.createElement("abc") 
eh = doc.createElement("hello") 
s1 = 'bhaskar' 
text = doc.createTextNode(s1) 

eh.appendChild(text) 
e.appendChild(eh) 

e.toxml() 

編輯:我不知道什麼Python的API是什麼樣子,但看上去非常類似於C#的,所以你也許可以做到像e.innerXml = s1做你想做什麼。 ..但那可能是不好的。要做的更好的事情是解析它,並且它也是。

編輯2:我剛剛通過Python在本地運行這個,並且在你的結尾肯定有錯誤,而不是在庫中。使確定您的字符串在其開頭沒有任何換行符或空格。作爲參考,我使用的測試代碼爲:

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41) 
[GCC 4.3.3] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from xml.dom.minidom import Document 
>>> cert = "---- START CERTIFICATE ----\n Hello world\n---- END CERTIFICATE ---" 
>>> doc = Document() 
>>> e = doc.createElement("cert") 
>>> certEl = doc.createTextNode(cert) 
>>> e.appendChild(certEl) 
<DOM Text node "'---- START'..."> 
>>> print e.toxml() 
<cert>---- START CERTIFICATE ---- 
    Hello world 
---- END CERTIFICATE ---</cert> 
>>> 

EDIT 3:最終編輯。問題出在您撥打writexml。只需用下面的修復此:

doc.writexml(fobj) 
# or 
doc.writexml(fobj, "", " ", "") 

Unfortuanately,看來你將無法使用newline參數,但得到相當的印刷...看來,Python庫(或至少minidom)是寫得相當不好,並會在打印時修改TextNode。與其說天真的執行不力,不如說是一個糟糕的實現。真是很遺憾... ...

+0

是的,是的。有一個原因,爲什麼這個方法被稱爲_'createTextNode'_。 – Boldewyn 2009-10-26 08:26:23

+0

感謝您的回覆。我之前使用元素並附加文本節點。但它讓我陷入了一個問題。看到我的迴應。 – user193287 2009-10-26 08:32:10

+0

重新編輯3 - 非常感謝馬修 是的所有漂亮都失去了:) – user193287 2009-10-26 13:31:36

3

如果使用"<"作爲XML文本,你需要逃避它,否則它被認爲是標記。所以xml.dom在轉義它是正確的,因爲你已經要求一個文本節點。

假設你確實想插入一段XML,我推薦使用createElement("hello")。如果您有一段不知道其結構的XML片段,則應首先對其進行解析,然後將解析結果的節點移動到另一個樹中。

如果你想破解,你可以從xml.dom.minidom.Text繼承,並覆蓋writexml方法。詳情請參閱minidom的來源。