Экранирование '<' и '>' в xml при использовании xml.dom.minidom - PullRequest
1 голос
/ 26 октября 2009

Я застрял при экранировании "<" и ">" в файле xml с помощью xml.dom.minidom. Я попытался получить шестнадцатеричное значение Юникода и использовать его вместо
http://slayeroffice.com/tools/unicode_lookup/

Пытался использовать стандартные "<" и ">", но безуспешно.

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 () Также пытался указать кодировку 'UTF-8', 'utf-8', 'utf' в вызовах toxml () writexml (), но с теми же результатами.

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>

Обратите внимание, что «Это сертификат» поставляется отдельно Сломал мне голову над этим, но с теми же результатами.

Ответы [ 2 ]

6 голосов
/ 26 октября 2009

Это не ошибка, это особенность.Чтобы вставить настоящий 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()

РЕДАКТИРОВАТЬ: Я не знаю, на что похож API-интерфейс Python, но он выглядит очень похоже наC #, так что вы можете сделать что-то вроде e.innerXml = s1, чтобы делать то, что вы пытаетесь сделать ... но это может быть плохо.Лучше всего разобрать и appendChild это тоже.

РЕДАКТИРОВАТЬ 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>
>>> 

РЕДАКТИРОВАТЬ 3: Окончательное редактирование.Проблема в вашем writexml звонке.Простое использование следующего исправляет это:

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

К сожалению, кажется, что вы не сможете использовать параметр newline, чтобы получить красивую печать, хотя ... кажется, что библиотека Python (илипо крайней мере minidom) написано довольно плохо и будет изменять текстовые узлы при их печати.Не столько плохая реализация, сколько наивная.Стыд действительно ...

3 голосов
/ 26 октября 2009

Если вы используете "<" в качестве текста в XML, вам нужно экранировать его, иначе это считается разметкой. Так что xml.dom прав, поскольку вы запросили текстовый узел.

Если вы действительно хотите вставить фрагмент XML, я рекомендую использовать createElement("hello"). Если у вас есть фрагмент XML, структура которого вам неизвестна, вы должны сначала проанализировать его, а затем переместить узлы этого результата анализа в другое дерево.

Если вы хотите взломать, вы можете наследовать от xml.dom.minidom.Text и перезаписать метод writexml. Подробности смотрите в источнике минидома.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...