Kaydet (Commit) acd32d3b authored tarafından Fred Drake's avatar Fred Drake

Added function xml.sax.saxutils.quoteattr().

This closes SF bug #440351.  It should not be moved to Python 2.1.1.
üst 3c033230
...@@ -14,13 +14,33 @@ functions that are commonly useful when creating SAX applications, ...@@ -14,13 +14,33 @@ functions that are commonly useful when creating SAX applications,
either in direct use, or as base classes. either in direct use, or as base classes.
\begin{funcdesc}{escape}{data\optional{, entities}} \begin{funcdesc}{escape}{data\optional{, entities}}
Escape \&, <, and > in a string of data. Escape \character{\&}, \character{<}, and \character{>} in a string
of data.
You can escape other strings of data by passing a dictionary as the You can escape other strings of data by passing a dictionary as the
optional entities parameter. The keys and values must all be optional \var{entities} parameter. The keys and values must all be
strings; each key will be replaced with its corresponding value. strings; each key will be replaced with its corresponding value.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{quoteattr}{data\optional{, entities}}
Similar to \function{escape()}, but also prepares \var{data} to be
used as an attribute value. The return value is a quoted version of
\var{data} with any additional required replacements.
\function{quoteattr()} will select a quote character based on the
content of \var{data}, attempting to avoid encoding any quote
characters in the string. If both single- and double-quote
characters are already in \var{data}, the double-quote characters
will be encoded and \var{data} will be wrapped in doule-quotes. The
resulting string can be used directly as an attribute value:
\begin{verbatim}
>>> print "<element attr=%s>" % quoteattr("ab ' cd \" ef")
<element attr="ab ' cd &quot; ef">
\end{verbatim}
\versionadded{2.2}
\end{funcdesc}
\begin{classdesc}{XMLGenerator}{\optional{out\optional{, encoding}}} \begin{classdesc}{XMLGenerator}{\optional{out\optional{, encoding}}}
This class implements the \class{ContentHandler} interface by This class implements the \class{ContentHandler} interface by
writing SAX events back into an XML document. In other words, using writing SAX events back into an XML document. In other words, using
......
test_sax test_sax
Passed test_attrs_empty Passed test_attrs_empty
Passed test_attrs_wattr Passed test_attrs_wattr
Passed test_double_quoteattr
Passed test_escape_all Passed test_escape_all
Passed test_escape_basic Passed test_escape_basic
Passed test_escape_extra Passed test_escape_extra
...@@ -25,10 +26,13 @@ Passed test_make_parser ...@@ -25,10 +26,13 @@ Passed test_make_parser
Passed test_make_parser2 Passed test_make_parser2
Passed test_nsattrs_empty Passed test_nsattrs_empty
Passed test_nsattrs_wattr Passed test_nsattrs_wattr
Passed test_quoteattr_basic
Passed test_single_double_quoteattr
Passed test_single_quoteattr
Passed test_xmlgen_basic Passed test_xmlgen_basic
Passed test_xmlgen_content Passed test_xmlgen_content
Passed test_xmlgen_content_escape Passed test_xmlgen_content_escape
Passed test_xmlgen_ignorable Passed test_xmlgen_ignorable
Passed test_xmlgen_ns Passed test_xmlgen_ns
Passed test_xmlgen_pi Passed test_xmlgen_pi
32 tests, 0 failures 36 tests, 0 failures
...@@ -8,7 +8,7 @@ try: ...@@ -8,7 +8,7 @@ try:
except SAXReaderNotAvailable: except SAXReaderNotAvailable:
# don't try to test this module if we cannot create a parser # don't try to test this module if we cannot create a parser
raise ImportError("no XML parsers available") raise ImportError("no XML parsers available")
from xml.sax.saxutils import XMLGenerator, escape, XMLFilterBase from xml.sax.saxutils import XMLGenerator, escape, quoteattr, XMLFilterBase
from xml.sax.expatreader import create_parser from xml.sax.expatreader import create_parser
from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
from cStringIO import StringIO from cStringIO import StringIO
...@@ -69,6 +69,25 @@ def test_escape_all(): ...@@ -69,6 +69,25 @@ def test_escape_all():
def test_escape_extra(): def test_escape_extra():
return escape("Hei p deg", {"" : "&aring;"}) == "Hei p&aring; deg" return escape("Hei p deg", {"" : "&aring;"}) == "Hei p&aring; deg"
# ===== quoteattr
def test_quoteattr_basic():
return quoteattr("Donald Duck & Co") == '"Donald Duck &amp; Co"'
def test_single_quoteattr():
return (quoteattr('Includes "double" quotes')
== '\'Includes "double" quotes\'')
def test_double_quoteattr():
return (quoteattr("Includes 'single' quotes")
== "\"Includes 'single' quotes\"")
def test_single_double_quoteattr():
return (quoteattr("Includes 'single' and \"double\" quotes")
== "\"Includes 'single' and &quot;double&quot; quotes\"")
# ===== make_parser
def test_make_parser(): def test_make_parser():
try: try:
# Creating a parser should succeed - it should fall back # Creating a parser should succeed - it should fall back
......
...@@ -27,6 +27,27 @@ def escape(data, entities={}): ...@@ -27,6 +27,27 @@ def escape(data, entities={}):
data = data.replace(chars, entity) data = data.replace(chars, entity)
return data return data
def quoteattr(data, entities={}):
"""Escape and quote an attribute value.
Escape &, <, and > in a string of data, then quote it for use as
an attribute value. The \" character will be escaped as well, if
necessary.
You can escape other strings of data by passing a dictionary as
the optional entities parameter. The keys and values must all be
strings; each key will be replaced with its corresponding value.
"""
data = escape(data, entities)
if '"' in data:
if "'" in data:
data = '"%s"' % data.replace('"', "&quot;")
else:
data = "'%s'" % data
else:
data = '"%s"' % data
return data
class XMLGenerator(handler.ContentHandler): class XMLGenerator(handler.ContentHandler):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment