Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit acd32d3

Browse files
committed
Added function xml.sax.saxutils.quoteattr().
This closes SF bug #440351. It should not be moved to Python 2.1.1.
1 parent 3c03323 commit acd32d3

4 files changed

Lines changed: 68 additions & 4 deletions

File tree

Doc/lib/xmlsaxutils.tex

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,33 @@ \section{\module{xml.sax.saxutils} ---
1414
either in direct use, or as base classes.
1515

1616
\begin{funcdesc}{escape}{data\optional{, entities}}
17-
Escape \&, <, and > in a string of data.
17+
Escape \character{\&}, \character{<}, and \character{>} in a string
18+
of data.
1819

1920
You can escape other strings of data by passing a dictionary as the
20-
optional entities parameter. The keys and values must all be
21+
optional \var{entities} parameter. The keys and values must all be
2122
strings; each key will be replaced with its corresponding value.
2223
\end{funcdesc}
2324

25+
\begin{funcdesc}{quoteattr}{data\optional{, entities}}
26+
Similar to \function{escape()}, but also prepares \var{data} to be
27+
used as an attribute value. The return value is a quoted version of
28+
\var{data} with any additional required replacements.
29+
\function{quoteattr()} will select a quote character based on the
30+
content of \var{data}, attempting to avoid encoding any quote
31+
characters in the string. If both single- and double-quote
32+
characters are already in \var{data}, the double-quote characters
33+
will be encoded and \var{data} will be wrapped in doule-quotes. The
34+
resulting string can be used directly as an attribute value:
35+
36+
\begin{verbatim}
37+
>>> print "<element attr=%s>" % quoteattr("ab ' cd \" ef")
38+
<element attr="ab ' cd &quot; ef">
39+
\end{verbatim}
40+
41+
\versionadded{2.2}
42+
\end{funcdesc}
43+
2444
\begin{classdesc}{XMLGenerator}{\optional{out\optional{, encoding}}}
2545
This class implements the \class{ContentHandler} interface by
2646
writing SAX events back into an XML document. In other words, using

Lib/test/output/test_sax

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
test_sax
22
Passed test_attrs_empty
33
Passed test_attrs_wattr
4+
Passed test_double_quoteattr
45
Passed test_escape_all
56
Passed test_escape_basic
67
Passed test_escape_extra
@@ -25,10 +26,13 @@ Passed test_make_parser
2526
Passed test_make_parser2
2627
Passed test_nsattrs_empty
2728
Passed test_nsattrs_wattr
29+
Passed test_quoteattr_basic
30+
Passed test_single_double_quoteattr
31+
Passed test_single_quoteattr
2832
Passed test_xmlgen_basic
2933
Passed test_xmlgen_content
3034
Passed test_xmlgen_content_escape
3135
Passed test_xmlgen_ignorable
3236
Passed test_xmlgen_ns
3337
Passed test_xmlgen_pi
34-
32 tests, 0 failures
38+
36 tests, 0 failures

Lib/test/test_sax.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
except SAXReaderNotAvailable:
99
# don't try to test this module if we cannot create a parser
1010
raise ImportError("no XML parsers available")
11-
from xml.sax.saxutils import XMLGenerator, escape, XMLFilterBase
11+
from xml.sax.saxutils import XMLGenerator, escape, quoteattr, XMLFilterBase
1212
from xml.sax.expatreader import create_parser
1313
from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
1414
from cStringIO import StringIO
@@ -69,6 +69,25 @@ def test_escape_all():
6969
def test_escape_extra():
7070
return escape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
7171

72+
# ===== quoteattr
73+
74+
def test_quoteattr_basic():
75+
return quoteattr("Donald Duck & Co") == '"Donald Duck &amp; Co"'
76+
77+
def test_single_quoteattr():
78+
return (quoteattr('Includes "double" quotes')
79+
== '\'Includes "double" quotes\'')
80+
81+
def test_double_quoteattr():
82+
return (quoteattr("Includes 'single' quotes")
83+
== "\"Includes 'single' quotes\"")
84+
85+
def test_single_double_quoteattr():
86+
return (quoteattr("Includes 'single' and \"double\" quotes")
87+
== "\"Includes 'single' and &quot;double&quot; quotes\"")
88+
89+
# ===== make_parser
90+
7291
def test_make_parser():
7392
try:
7493
# Creating a parser should succeed - it should fall back

Lib/xml/sax/saxutils.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,27 @@ def escape(data, entities={}):
2727
data = data.replace(chars, entity)
2828
return data
2929

30+
def quoteattr(data, entities={}):
31+
"""Escape and quote an attribute value.
32+
33+
Escape &, <, and > in a string of data, then quote it for use as
34+
an attribute value. The \" character will be escaped as well, if
35+
necessary.
36+
37+
You can escape other strings of data by passing a dictionary as
38+
the optional entities parameter. The keys and values must all be
39+
strings; each key will be replaced with its corresponding value.
40+
"""
41+
data = escape(data, entities)
42+
if '"' in data:
43+
if "'" in data:
44+
data = '"%s"' % data.replace('"', "&quot;")
45+
else:
46+
data = "'%s'" % data
47+
else:
48+
data = '"%s"' % data
49+
return data
50+
3051

3152
class XMLGenerator(handler.ContentHandler):
3253

0 commit comments

Comments
 (0)