class ElementElement(XsltElement): category = CategoryTypes.INSTRUCTION content = ContentInfo.Template legalAttrs = { 'name': AttributeInfo.RawQNameAvt(required=1), 'namespace': AttributeInfo.UriReferenceAvt(isNsName=1), 'use-attribute-sets': AttributeInfo.QNames(), } def instantiate(self, context, processor): context.processorNss = self.namespaces context.currentInstruction = self (prefix, local) = self._name.evaluate(context) if prefix is not None: name = prefix + u':' + local else: name = local # From sec. 7.1.2 of the XSLT spec, # 1. if 'namespace' attr is not present, use ns in scope, based on prefix # from the element QName in the 'name' attr value; if no prefix, use # default ns in scope # 2. if 'namespace' attr is present and empty string, use empty ns ALWAYS # 3. if 'namespace' attr is present, namespace is attr value # if not self._namespace: if prefix is not None: if not self.namespaces.has_key(prefix): raise XsltRuntimeException(Error.UNDEFINED_PREFIX, self, prefix) namespace = self.namespaces[prefix] else: namespace = self.namespaces[None] else: namespace = (self._namespace and self._namespace.evaluate(context) or EMPTY_NAMESPACE) self.execute(context, processor, name, namespace) return def execute(self, context, processor, name, namespace): #FIXME: Use proper pysax AttributeList objects processor.writers[-1].startElement(name, namespace) for attr_set_name in self._use_attribute_sets: try: attr_set = processor.attributeSets[attr_set_name] except KeyError: raise XsltRuntimeException(Error.UNDEFINED_ATTRIBUTE_SET, self, attr_set_name) attr_set.instantiate(context, processor) for child in self.children: child.instantiate(context, processor) processor.writers[-1].endElement(name, namespace) return
class OutputElement(XsltElement): category = CategoryTypes.TOP_LEVEL_ELEMENT content = ContentInfo.Empty legalAttrs = { 'method' : AttributeInfo.QName(), 'version' : AttributeInfo.NMToken(), 'encoding' : AttributeInfo.String(), 'omit-xml-declaration' : AttributeInfo.YesNo(), 'standalone' : AttributeInfo.YesNo(), 'doctype-public' : AttributeInfo.String(), 'doctype-system' : AttributeInfo.String(), 'cdata-section-elements' : AttributeInfo.QNames(), 'indent' : AttributeInfo.YesNo(), 'media-type' : AttributeInfo.String(), 'f:utfbom' : AttributeInfo.YesNo( default='no', description='Whether to force output of a byte order mark (BOM). Usually used to generate a UTF-8 BOM. Do not use unless you\'re sure you know what you\'re doing'), }
class AttributeSetElement(XsltElement): category = CategoryTypes.TOP_LEVEL_ELEMENT content = ContentInfo.Rep(ContentInfo.QName(XSL_NAMESPACE, 'xsl:attribute')) legalAttrs = { 'name': AttributeInfo.QName(required=1), 'use-attribute-sets': AttributeInfo.QNames(), } doesPrime = 1 def prime(self, processor, context): processor.attributeSets[self._name] = self return def instantiate(self, context, processor, used=None): if used is None: used = [] if self in used: raise XsltRuntimeException(Error.CIRCULAR_ATTRIBUTE_SET, self, self._name) else: used.append(self) old_vars = context.varBindings context.varBindings = processor.stylesheet.getGlobalVariables() for attr_set_name in self._use_attribute_sets: try: attr_set = processor.attributeSets[attr_set_name] except KeyError: raise XsltRuntimeException(Error.UNDEFINED_ATTRIBUTE_SET, self, attr_set_name) attr_set.instantiate(context, processor, used) for child in self.children: child.instantiate(context, processor) context.varBindings = old_vars used.remove(self) return
class UriToElementElement(ElementElement.ElementElement): """ Extends xsl:element by deriving the constructed element's QName and namespace from the supplied URI reference. The URI reference is first resolved to absolute form. Then, if the resulting URI begins with an in-scope namespace, that namespace will be used as if it had been supplied as the 'namespace' attribute to xsl:element, and the remainder of the URI will be combined with a prefix from the in-scope namespace bindings and used as if supplied as the 'name' attribute to xsl:element. Otherwise, the supplied default-name and default-namespace will be used, effecting the same result as calling xsl:element with these values. The intent is to allow an RDF resource, as identified by a URI with a fragment component, to be easily converted into an element. """ content = ContentInfo.Template legalAttrs = { 'uri': AttributeInfo.UriReferenceAvt( description= 'A URI to be used to create the element. An attempt will be made to split the URI into a head and a tail such that the head matches an in-scope namespace URI. If matched a qname will be constructed from the prefix of that namespace declaration and the tail of the URI and the namespace from the declaration will be used to complete an output element.', required=1), 'default-name': AttributeInfo.RawQNameAvt( description= 'Used if the given URI cannot be broken down using in-scope namespaces', required=1), 'default-namespace': AttributeInfo.UriReferenceAvt( description= 'Used if the given URI cannot be broken down using in-scope namespaces', isNsName=1), 'use-attribute-sets': AttributeInfo.QNames(), } def instantiate(self, context, processor): context.currentInstruction = self matched = 0 uri = self._uri.evaluate(context) for (prefix, namespace) in self.namespaces.items(): if namespace and uri.startswith(namespace): local = uri.split(namespace)[1] if prefix: qname = prefix + u':' + local else: qname = local matched = 1 break if matched: ElementElement.ElementElement.execute(self, context, processor, qname, namespace) return else: self._name = self._default_name self._namespace = self._default_namespace return ElementElement.ElementElement.instantiate( self, context, processor)
class CopyElement(XsltElement): category = CategoryTypes.INSTRUCTION content = ContentInfo.Template legalAttrs = { 'use-attribute-sets': AttributeInfo.QNames(), } def instantiate(self, context, processor): context.processorNss = self.namespaces node = context.node if node.nodeType == Node.TEXT_NODE: processor.writers[-1].text(node.data) elif node.nodeType == Node.ELEMENT_NODE: #FIXME: Use proper pysax AttributeList objects extraNss = {} for (namespace, local), attr in node.attributes.items(): # Namespace nodes are automatically copied as well # See XSLT 1.0 Sect 7.5 if namespace == XMLNS_NAMESPACE: extraNss[local] = attr.value processor.writers[-1].startElement(node.nodeName, node.namespaceURI, extraNss) for attr_set_name in self._use_attribute_sets: try: attr_set = processor.attributeSets[attr_set_name] except KeyError: raise XsltRuntimeException(Error.UNDEFINED_ATTRIBUTE_SET, self, attr_set_name) attr_set.instantiate(context, processor) for child in self.children: child.instantiate(context, processor) processor.writers[-1].endElement(node.nodeName, node.namespaceURI) elif node.nodeType == Node.DOCUMENT_NODE: for child in self.children: child.instantiate(context, processor) elif node.nodeType == Node.ATTRIBUTE_NODE: if node.namespaceURI != XMLNS_NAMESPACE: processor.writers[-1].attribute(node.nodeName, node.nodeValue, node.namespaceURI) elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE: processor.writers[-1].processingInstruction(node.target, node.data) elif node.nodeType == Node.COMMENT_NODE: processor.writers[-1].comment(node.data) elif node.nodeType == NAMESPACE_NODE: #Relies on XmlWriter rules, which is very close to spec: #http://www.w3.org/1999/11/REC-xslt-19991116-errata/#E25 processor.writers[-1]._namespaces[-1][ node.nodeName] = node.nodeValue else: raise Exception("Unknown Node Type %d" % node.nodeType) return