Commits

Walter Dörwald  committed 542fad7

asString() benutzt jetzt intern publish(), dieser Funktion kann ein
publisher übergeben werden, eine Funktion (oder ein Objekt mit implementiertem
__call__), der die zu auszugebenden Strings übergeben werden. asString()
baut auf dieser Funktion auf und benutzt dazu die Klasse StringPublisher.

Ein paar kleine Bugfixes in errors.py

  • Participants
  • Parent commits f79bd83
  • Tags rel-0-3-5

Comments (0)

Files changed (3)

File xist/errors.py

 			elementnames.append(xsc._strNode(xsc._elementHandlers[self.name[1]][namespace]))
 		elementnames.sort()
 
-		return Error.__str__(self) + "element " + _strName((self.name[0],self.name[1],0)) + " is ambigous. Possible elements are: " + string.join(elementnames,", ") + "."
+		return Error.__str__(self) + "element " + xsc._strName((self.name[0],self.name[1],0)) + " is ambigous. Possible elements are: " + string.join(elementnames,", ") + "."
 

File xist/publishers.py

+#! /usr/bin/env python
+
+## Copyright 1999-2000 by Living Logic AG, Bayreuth, Germany.
+## Copyright 1999-2000 by Walter Dörwald
+##
+## See the file LICENSE for licensing details
+
+import sys
+import string
+
+class PrintPublisher:
+	def __call__(self,*texts):
+		for text in texts:
+			sys.stdout.write(text)
+
+class StringPublisher:
+	def __init__(self):
+		self.texts = []
+
+	def __call__(self,*texts):
+		for text in texts:
+			self.texts.append(text)
+
+	def __str__(self):
+		return string.join(self.texts,"")
+
 # our own new URL class
 from URL import URL
 
+from publishers import StringPublisher
+
 # exceptions
 from errors import *
 
 repransiprocinsttarget = getANSICodesFromEnv("XSC_REPRANSI_PROCINSTTARGET",[ "1;31","1;31" ])   # ANSI escape sequence to be used for processing instruction targets
 repransiprocinstdata = getANSICodesFromEnv("XSC_REPRANSI_PROCINSTDATA",[ "","" ])               # ANSI escape sequence to be used for processing instruction data
 outputXHTML = getIntFromEnv("XSC_OUTPUT_XHTML",1)                                               # XHTML output format (0 = plain HTML, 1 = HTML compatible XHTML, 2 = pure XHTML)
-outputEncoding = getStringFromEnv("XSC_OUTPUT_ENCODING","us-ascii")                             # Encoding to be used in asString()
+outputEncoding = getStringFromEnv("XSC_OUTPUT_ENCODING","us-ascii")                             # Encoding to be used in publish() (and asString())
 
 ###
 ### helpers
 			return node
 	raise IllegalObjectError(-1,value) # none of the above, so we throw and exception
 
+def encode(text,encoding):
+	v = []
+	for i in self.content:
+		if i == '\r':
+			continue
+		if self.strescapes.has_key(i):
+			v.append('&' + self.strescapes[i] + ';')
+		elif ord(i)>=128:
+			v.append('&#' + str(ord(i)) + ';')
+		else:
+			v.append(i)
+	return string.join(v,"")
+
 # dictionary for mapping element names to classes, this dictionary contains
 # the element names as keys and another dictionary as values, this second
 # dictionary contains the namespace names as keys and the element classes as values
 class Node:
 	"""
 	base class for nodes in the document tree. Derived classes must
-	implement asHTML() and/or asString()
+	implement asHTML() and/or publish()
 	"""
 
 	empty = 1
 			s = string.replace(s,decimal,".")
 		return float(s)
 
-	def asString(self,XHTML = None,encoding = None):
+	def publish(self,publisher,XHTML = None,encoding = None):
 		"""
-		<par noindent>returns this element as a string suitable for writing
-		to an HTML file or printing from a CGI script.</par>
+		<par noindent>generates string suitable for writing
+		to an HTML file or printing from a CGI script. The pieces
+		of the final string are passed to the callable object
+		<argref>publisher</argref>.</par>
 
 		<par>With the parameter <argref>XHTML</argref> you can specify if you want HTML output
 		(i.e. elements with a content model EMPTY as <code>&lt;foo&gt;</code>) with
 		outputXHTML will be used, which defaults to 1, but can be overwritten
 		by the environment variable XSC_OUTPUT_XHTML and can of course be
 		changed dynamically.</par>
-
-		<par>There will only be 7bit characters in the string, so can use "us-ascii"
-		as the chraracter set.</par>
 		"""
 		return ""
 
-	def findNodes(self,type = None,subtype = 0,attrs = None,test = None,searchchildren = 0,searchattrs = 0):
+
+	def asString(self,XHTML = None,encoding = None):
+		"""
+		<par noindent>returns this element as a string suitable for writing
+		to an HTML file or printing from a CGI script.</par>
+
+		<par>For the rest of the parameters see <funcref>publish</funcref>.</par>
+		"""
+		publisher = StringPublisher()
+		self.publish(publisher,XHTML,encoding)
+		return str(publisher)
+
+	def find(self,type = None,subtype = 0,attrs = None,test = None,searchchildren = 0,searchattrs = 0):
 		"""
 		<par noindent>returns a fragment which contains child elements of this node.</par>
 
 	def asPlainString(self):
 		return self.content
 
-	def asString(self,XHTML = None,encoding = None):
-		v = []
+	def publish(self,publisher,XHTML = None,encoding = None):
 		for i in self.content:
 			if i == '\r':
 				continue
 			if self.strescapes.has_key(i):
-				v.append('&' + self.strescapes[i] + ';')
+				publisher('&' + self.strescapes[i] + ';')
 			elif ord(i)>=128:
-				v.append('&#' + str(ord(i)) + ';')
+				publisher('&#' + str(ord(i)) + ';')
 			else:
-				v.append(i)
-		return string.join(v,"")
+				publisher(i)
 
 	def __strtext(self,refwhite,content,ansi = None):
 		# we could put ANSI escapes around every character or reference that we output,
 	def asPlainString(self):
 		return chr(self.content)
 
-	def asString(self,XHTML = None,encoding = None):
+	def publish(self,publisher,XHTML = None,encoding = None):
 		if 0<=self.content<=127:
 			if self.content != ord("\r"):
 				if self.__notdirect.has_key(self.content):
-					return '&' + self.__notdirect[self.content] + ';'
+					publisher('&' + self.__notdirect[self.content] + ';')
 				else:
-					return chr(self.content)
+					publisher(chr(self.content))
 		else:
-			return '&#' + str(self.content) + ';'
+			publisher('&#' + str(self.content) + ';')
 
 	def __strcharref(self,s,ansi = None):
 		return strCharRef(s,ansi)
 			v.append(child.asPlainString())
 		return string.join(v,"")
 
-	def asString(self,XHTML = None,encoding = None):
-		v = []
+	def publish(self,publisher,XHTML = None,encoding = None):
 		for child in self:
-			v.append(child.asString(XHTML))
-		return string.join(v,"")
+			child.publish(publisher,XHTML,encoding)
 
 	def __getitem__(self,index):
 		"""
 			elif newother is not Null:
 				self.__content.append(newother)
 
-	def findNodes(self,type = None,subtype = 0,attrs = None,test = None,searchchildren = 0,searchattrs = 0):
+	def find(self,type = None,subtype = 0,attrs = None,test = None,searchchildren = 0,searchattrs = 0):
 		node = Frag()
 		for child in self:
 			if child._matches(type,subtype,attrs,test):
 				node.append(child)
 			if searchchildren:
-				node.extend(child.findNodes(type,subtype,attrs,test,searchchildren,searchattrs))
+				node.extend(child.find(type,subtype,attrs,test,searchchildren,searchattrs))
 		return node
 
 	def compact(self):
 		tail = strCommentMarker(ansi) + strBracketClose(ansi)
 		return self._doreprtreeMultiLine(nest,elementno,head,tail,self.content,strCommentText,0,ansi = ansi)
 
-	def asString(self,XHTML = None,encoding = None):
-		return "<!--" + self.content + "-->"
+	def publish(self,publisher,XHTML = None,encoding = None):
+		publisher("<!--" + self.content + "-->")
 
 	def compact(self):
 		return self._decorateNode(Comment(self.content))
 	def _doreprtree(self,nest,elementno,ansi = None):
 		return [[nest,self.startloc,elementno,self._dorepr(ansi)]]
 
-	def asString(self,XHTML = None,encoding = None):
-		return "<!DOCTYPE " + self.content + ">"
+	def publish(self,publisher,XHTML = None,encoding = None):
+		publisher("<!DOCTYPE " + self.content + ">")
 
 	def compact(self):
 		return self._decorateNode(DocType(self.content))
 		tail = strQuestion(ansi) + strBracketClose(ansi)
 		return self._doreprtreeMultiLine(nest,elementno,head,tail,self.content,strProcInstData,1,ansi = ansi)
 
-	def asString(self,XHTML = None,encoding = None):
-		return "<?" + self.target + " " + self.content + "?>"
+	def publish(self,publisher,XHTML = None,encoding = None):
+		publisher("<?",self.target," ",self.content,"?>")
 
 	def compact(self):
 		return self._decorateNode(ProcInst(self.target,self.content))
 				v.append([nest,self.endloc,elementno,self._str(brackets = 1,slash = -1,ansi = ansi)])
 		return v
 
-	def _asStringWithImageSize(self,XHTML = None,encoding = None,imgattr = None,widthattr = None,heightattr = None):
+	def _publishWithImageSize(self,publisher,XHTML = None,encoding = None,imgattr = None,widthattr = None,heightattr = None):
 		"""
 		<par noindent>generates a string representing the element and adds width and height
 		attributes in the process. The URL for the image is fetched for the attribute named
 		will be done.</par>
 		"""
 
-		v = []
-		v.append("<")
-		v.append(self.elementname) # requires that the element is registered via registerElement()
+		publisher("<",self.elementname) # requires that the element is registered via registerElement()
 		if imgattr is not None:
 			size = self[imgattr].asHTML().ImageSize()
 			sizedict = { "width": size[0], "height": size[1] }
 		else:
 			size = None
 		for attr in self.attrs.keys():
-			v.append(' ')
-			v.append(attr)
+			publisher(' ',attr)
 			value = self[attr]
 			if len(value):
-				v.append('="')
+				publisher('="')
 				if size is not None and attr==widthattr:
 					try:
-						v.append(str(eval(self[widthattr].asPlainString() % sizedict)))
+						publisher(str(eval(self[widthattr].asPlainString() % sizedict)))
 					except:
 						raise ImageSizeFormatError(self,widthattr)
 				elif size is not None and attr==heightattr:
 					try:
-						v.append(str(eval(self[heightattr].asPlainString() % sizedict)))
+						publisher(str(eval(self[heightattr].asPlainString() % sizedict)))
 					except:
 						raise ImageSizeFormatError(self,heightattr)
 				else:
-					v.append(value.asString(XHTML))
-				v.append('"')
+					value.publish(XHTML,encoding)
+				publisher('"')
 		if size is not None:
 			if widthattr is not None and not self.hasAttr(widthattr):
-				v.append(' ')
-				v.append(widthattr)
-				v.append('="')
-				v.append(str(size[0]))
-				v.append('"')
+				publisher(' ',widthattr,'="',str(size[0]),'"')
 			if heightattr is not None and not self.hasAttr(heightattr):
-				v.append(' ')
-				v.append(heightattr)
-				v.append('="')
-				v.append(str(size[1]))
-				v.append('"')
+				publisher(' ',heightattr,'="',str(size[1]),'"')
 		if len(self):
 			if self.empty:
 				raise EmptyElementWithContentError(self)
-			v.append(">")
-			v.append(self.content.asString(XHTML))
-			v.append("</")
-			v.append(self.elementname)
-			v.append(">")
+			publisher(">")
+			self.content.publish(publisher,XHTML,encoding)
+			publisher("</",self.elementname,">")
 		else:
 			if XHTML is None:
 				XHTML = outputXHTML
 			if XHTML in (0,1):
 				if self.empty:
 					if XHTML==1:
-						v.append(" /")
-					v.append(">")
+						publisher(" /")
+					publisher(">")
 				else:
-					v.append("></")
-					v.append(self.elementname)
-					v.append(">")
+					publisher("></",self.elementname,">")
 			elif XHTML == 2:
-				v.append("/>")
+				publisher("/>")
 			else:
 				raise ValueError("XHTML must be 0, 1, 2 or None")
 
-		return string.join(v,"")
-
-	def asString(self,XHTML = None,encoding = None):
-		return self._asStringWithImageSize(XHTML,encoding)
+	def publish(self,publisher,XHTML = None,encoding = None):
+		return self._publishWithImageSize(publisher,XHTML,encoding)
 
 	def __getitem__(self,index):
 		"""
 			node[attr] = self[attr].compact()
 		return self._decorateNode(node)
 
-	def findNodes(self,type = None,subtype = 0,attrs = None,test = None,searchchildren = 0,searchattrs = 0):
+	def find(self,type = None,subtype = 0,attrs = None,test = None,searchchildren = 0,searchattrs = 0):
 		node = Frag()
 		if searchattrs:
 			for attr in self.attrs.keys():
-				node.extend(self[attr].findNodes(type,subtype,attrs,test,searchchildren,searchattrs))
-		node.extend(self.content.findNodes(type,subtype,attrs,test,searchchildren,searchattrs))
+				node.extend(self[attr].find(type,subtype,attrs,test,searchchildren,searchattrs))
+		node.extend(self.content.find(type,subtype,attrs,test,searchchildren,searchattrs))
 		return node
 
 class Null(Node):
 
 	clone = compact = asHTML
 
-	def asString(self,XHTML = None,encoding = None):
-		return ""
+	def publish(self,publisher,XHTML = None,encoding = None):
+		pass
 
 	def _dorepr(self,ansi = None):
 		return self._str(slash = 1,ansi = ansi)
 	def _dorepr(self,ansi = None):
 		return strURL(self.asString(),ansi = ansi)
 
-	def asString(self,XHTML = None,encoding = None):
-		return Text(self.forOutput().asString()).asString(XHTML)
+	def publisher(self,XHTML = None,encoding = None):
+		Text(self.forOutput().asString()).publish(publisher,XHTML,encoding)
 
 	def asHTML(self):
 		node = Attr.asHTML(self)