diff --git a/package.sh b/package.sh
index 67bd6d2..70eab69 100755
--- a/package.sh
+++ b/package.sh
@@ -1,6 +1,6 @@
#!/bin/bash
SCOURVER="0.18"
cd ..
-tar cvf scour/tarballs/scour-$SCOURVER.tar scour/scour.py scour/svg_regex.py scour/LICENSE scour/NOTICE scour/README.txt scour/release-notes.html
-gzip scour/tarballs/scour-$SCOURVER.tar
+zip scour/tarballs/scour-$SCOURVER.zip scour/scour.py scour/svg_regex.py scour/LICENSE scour/NOTICE scour/README.txt scour/release-notes.html
cd scour
+zip tarballs/scour-inkscape-extension-$SCOURVER.zip scour.inx scour.inkscape.py scour.py svg_regex.py
diff --git a/release-notes.html b/release-notes.html
index 87805bf..1167be4 100644
--- a/release-notes.html
+++ b/release-notes.html
@@ -13,11 +13,11 @@
-
Aug 5th, 2009
+ Aug 9th, 2009
- Remove attributes of gradients if they contain default values
- Reduce bezier/quadratic (c/q) segments to their shorthand equivalents (s/t)
- - Custom XML serialization such that id/xml:id is printed first (Thanks to Richard Hutch for the suggestion)
+ - Move to a custom XML serialization such that id/xml:id is printed first (Thanks to Richard Hutch for the suggestion)
- Added --indent option to specify indentation type (default='space', other options: 'none', 'tab')
diff --git a/scour.py b/scour.py
index a43fae9..78d972c 100755
--- a/scour.py
+++ b/scour.py
@@ -1876,6 +1876,23 @@ def remapNamespacePrefix(node, oldprefix, newprefix):
for child in node.childNodes :
remapNamespacePrefix(child, oldprefix, newprefix)
+def makeWellFormed(str):
+ newstr = str
+
+ # encode & as & ( must do this first so that < does not become < )
+ if str.find('&') != -1:
+ newstr = str.replace('&', '&')
+
+ # encode < as <
+ if str.find("<") != -1:
+ newstr = str.replace('<', '<')
+
+ # encode > as > (TODO: is this necessary?)
+ if str.find('>') != -1:
+ newstr = str.replace('>', '>')
+
+ return newstr
+
# hand-rolled serialization function that has the following benefits:
# - pretty printing
# - somewhat judicious use of whitespace
@@ -1912,7 +1929,9 @@ def serializeXML(element, options, ind = 0):
if attr.nodeValue.find('"') != -1:
quot = "'"
- outString += ' ' + attr.nodeName + '=' + quot + attr.nodeValue + quot
+ attrValue = makeWellFormed( attr.nodeValue )
+
+ outString += ' ' + attr.nodeName + '=' + quot + attrValue + quot
# if no children, self-close
children = element.childNodes
@@ -1930,9 +1949,9 @@ def serializeXML(element, options, ind = 0):
# trim it only in the case of not being a child of an element
# where whitespace might be important
if element.nodeName in ["text", "tspan", "textPath", "tref", "title", "desc", "textArea"]:
- outString += child.nodeValue
+ outString += makeWellFormed(child.nodeValue)
else:
- outString += child.nodeValue.strip()
+ outString += makeWellFormed(child.nodeValue.strip())
# CDATA node
elif child.nodeType == 4:
outString += ''
diff --git a/scra.py b/scra.py
index 6775fc1..fe5807f 100644
--- a/scra.py
+++ b/scra.py
@@ -87,6 +87,7 @@ class ScourOptions:
embed_rasters = False
keep_editor_data = False
strip_xml_prolog = False
+ indent_type = "space"
# params are the form elements (if a checkbox is unchecked it will not be present)
def fetch(req, indoc,**params):
diff --git a/testscour.py b/testscour.py
index 7ffc315..12a2e77 100755
--- a/testscour.py
+++ b/testscour.py
@@ -833,6 +833,30 @@ class CDATAInXml(unittest.TestCase):
''',
'Improperly serialized the cdata unit tests')
+class WellFormedXMLLesserThanInAttrValue(unittest.TestCase):
+ def runTest(self):
+ wellformed = scour.scourString(open('unittests/xml-well-formed.svg').read())
+ self.assert_( wellformed.find('unicode="<"') != -1,
+ "Improperly serialized < in attribute value")
+
+class WellFormedXMLAmpersandInAttrValue(unittest.TestCase):
+ def runTest(self):
+ wellformed = scour.scourString(open('unittests/xml-well-formed.svg').read())
+ self.assert_( wellformed.find('unicode="&"') != -1,
+ 'Improperly serialized & in attribute value' )
+
+class WellFormedXMLLesserThanInTextContent(unittest.TestCase):
+ def runTest(self):
+ wellformed = scour.scourString(open('unittests/xml-well-formed.svg').read())
+ self.assert_( wellformed.find('2 < 5') != -1,
+ 'Improperly serialized < in text content')
+
+class WellFormedXMLAmpersandInTextContent(unittest.TestCase):
+ def runTest(self):
+ wellformed = scour.scourString(open('unittests/xml-well-formed.svg').read())
+ self.assert_( wellformed.find('Peanut Butter & Jelly') != -1,
+ 'Improperly serialized & in text content')
+
# TODO; write a test for embedding rasters
# TODO: write a test for --disable-embed-rasters
# TODO: write tests for --keep-editor-data
diff --git a/unittests/xml-well-formed.svg b/unittests/xml-well-formed.svg
new file mode 100644
index 0000000..dadf28d
--- /dev/null
+++ b/unittests/xml-well-formed.svg
@@ -0,0 +1,9 @@
+
+