def test_one_uri(count, uri, exception, tester=tester, module=domMod): tester.startTest("Document %d non-validating" % count) src = InputSource.DefaultFactory.fromUri(uri, BASE_PATH) if exception: tester.testException(module.NonvalParse, (src, ), ReaderException) else: doc = module.NonvalParse(src) stream = cStringIO.StringIO() Domlette.Print(doc, stream) src = InputSource.DefaultFactory.fromUri(uri, BASE_PATH) tester.compare(src.read(), stream.getvalue(), func=CompareXml) tester.testDone() tester.startTest("Document %d validating" % count) src = InputSource.DefaultFactory.fromUri(uri, BASE_PATH) if exception: tester.testException(module.NonvalParse, (src, ), ReaderException) else: doc = module.ValParse(src) stream = cStringIO.StringIO() Domlette.Print(doc, stream) src = InputSource.DefaultFactory.fromUri(uri, BASE_PATH) tester.compare(src.read(), stream.getvalue(), func=CompareXml) tester.testDone() return
def _xu_insert(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) for refnode in nodeset: self.pushDomResult(refnode.ownerDocument) try: for child in element.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() if element.localName == 'insert-before': refnode.parentNode.insertBefore(result, refnode) elif element.localName == 'insert-after': # if arg 2 is None, insertBefore behaves like appendChild refnode.parentNode.insertBefore(result, refnode.nextSibling) context.processorNss = oldNss return
def _xu_element(self, context, element, preserveSpace): name = element.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = element.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.writers[-1].startElement(name, namespace) for child in element.childNodes: self.visit(context, child, preserveSpace) self.writers[-1].endElement(name, namespace) context.processorNss = oldNss return
def _xu_attribute(self, context, node, preserveSpace): name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.pushStringResult() try: for child in node.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() self.writers[-1].attribute(name, result, namespace) context.processorNss = oldNss return
def doTest(tester, title, src, expected): tester.startTest(title) doc = READER.parseString(src, BASE_URI) st = cStringIO.StringIO() Domlette.Print(doc, stream=st) compared = st.getvalue() tester.compare(expected, compared, func=TreeCompare.XmlTreeCompare, diff=True) tester.testDone() return
def _xu_append(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) child = element.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()' oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not isinstance(nodeset, Types.NodesetType) or not nodeset: # Error if not a node-set or empty node-set raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) for refnode in nodeset: self.pushDomResult(refnode.ownerDocument) # A wrapper element is used in case attributes are being added wrapper_localName = 'wrapper' wrapper_namespace = EMPTY_NAMESPACE try: self.writers[-1].startElement(wrapper_localName, wrapper_namespace) for node in element.childNodes: self.visit(context, node, preserveSpace) finally: self.writers[-1].endElement(wrapper_localName, wrapper_namespace) result = self.popResult() size = len(refnode.childNodes) con = Context.Context(refnode, 1, size, processorNss={'xupdate': XUPDATE_NS}) # Python lists is 0-indexed counting, node-sets 1-indexed position = self.evaluateExpression(con, child) position = int(Conversions.NumberValue(position)) wrapper = result.childNodes[0] if wrapper.attributes and hasattr(refnode, 'setAttributeNodeNS'): for attr in wrapper.attributes.values(): refnode.setAttributeNodeNS(attr) # we operate on a shallow copy of the child nodes here to avoid # modifying the membership of the sequence we're interating over. for node in tuple(wrapper.childNodes): if position >= size: refnode.appendChild(node) else: refnode.insertBefore(node, refnode.childNodes[position]) context.processorNss = oldNss return
def _xu_if(self, context, element, preserveSpace): test = element.getAttributeNS(EMPTY_NAMESPACE, u'test') if not test: raise XUpdateException(XUpdateException.NO_TEST) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) result = self.evaluateExpression(context, test) if Conversions.BooleanValue(result): for node in element.childNodes: self.visit(context, node, preserveSpace) context.processorNss = oldNss return
def _xu_remove(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if nodeset: refnode = nodeset[0] if refnode.nodeType == Node.ATTRIBUTE_NODE: parent = refnode.ownerElement parent.removeAttributeNode(refnode) else: parent = refnode.parentNode if parent is None: parent = refnode.ownerDocument parent.removeChild(nodeset[0]) context.processorNss = oldNss return
def _xu_processing_instruction(self, context, element, preserveSpace): name = element.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) self.pushStringResult() try: for node in element.childNodes: self.visit(context, node, preserveSpace) finally: result = self.popResult() self.writers[-1].processingInstruction(name, result) context.processorNss = oldNss return
def _xu_rename(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) new_name = XmlStrStrip(element.firstChild.data) (prefix, local) = SplitQName(new_name) if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE for refnode in nodeset: if refnode.nodeType == Node.ATTRIBUTE_NODE: parent = refnode.ownerElement parent.removeAttributeNode(refnode) parent.setAttributeNS(namespace, new_name, refnode.value) else: parent = refnode.parentNode if parent is None: parent = refnode.ownerDocument new_elem = refnode.ownerDocument.createElementNS(namespace, new_name) parent.replaceChild(new_elem, refnode) # Copy any existing attributes to the newly created element if refnode.attributes: for attr in refnode.attributes.values(): new_elem.setAttributeNodeNS(attr) # Now copy any children as well while refnode.firstChild: new_elem.appendChild(refnode.firstChild) context.processorNss = oldNss return
def _xu_value_of(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) result = self.evaluateExpression(context, select) if isinstance(result, Types.NodesetType): for node in result: # should be OK to pass self as processor; # CopyNode only needs to access its .writers[-1] CopyNode(self, node) else: # a string, number or boolean if not isinstance(result, Types.StringType): result = Conversions.StringValue(result) self.writers[-1].text(result) context.processorNss = oldNss return
def _xu_variable(self, context, element, preserveSpace): name = element.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if select: oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) result = self.evaluateExpression(context, select) context.processorNss = oldNss else: result = Conversions.StringValue(element) (prefix, local) = SplitQName(name) if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE context.varBindings[(namespace, local)] = result return
def _xu_update(self, context, element, preserveSpace): select = element.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(element) nodeset = self.evaluateExpression(context, select) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, expr=select) refnode = nodeset[0] if refnode.nodeType == Node.ATTRIBUTE_NODE: self.pushStringResult() try: for child in element.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() refnode.value = result else: self.pushDomResult(refnode.ownerDocument) try: for child in element.childNodes: self.visit(context, child, preserveSpace) finally: result = self.popResult() while refnode.firstChild: refnode.removeChild(refnode.firstChild) refnode.appendChild(result) context.processorNss = oldNss return
def test_reader(tester, srcReader): processor = XUpdate.Processor() # ------------------------------------------------------ tester.startGroup('XUpdate instructions') for name, src, xuSrc, expected, vars_ in [ ("XUpdate spec example 1", src_1, xu_1, expected_1, {}), ("Append", src_2, xu_2, expected_2, {}), ("Update", src_3, xu_3, expected_3, {}), ("Remove", src_4, xu_4, expected_4, {}), ("Attribute/Value-Of", src_5, xu_5, expected_5, { (None, 'child-name'): "FOO" }), ("XUpdate spec append example", src_6, xu_6, expected_6, {}), ("Append attribute 1", src_7, xu_7, expected_7, {}), ("XUpdate use case 4", usecase_src, usecase_4, usecase_expected_4, {}), ("Rename", xu_rename_src, xu_rename, rename_expected, {}), ]: tester.startTest(name) uri = OsPathToUri('xupdate-test-src-' + quote(name) + '.xml', attemptAbsolute=True) isrc = InputSource.DefaultFactory.fromString(src, uri) src = srcReader(isrc) uri = OsPathToUri('xupdate-test-xup-' + quote(name) + '.xml', attemptAbsolute=True) isrc = InputSource.DefaultFactory.fromString(xuSrc, uri) xu = xureader.fromSrc(isrc) processor.execute(src, xu, variables=vars_) st = cStringIO.StringIO() Domlette.Print(src, stream=st) tester.compare(expected, st.getvalue(), func=TreeCompare.TreeCompare, diff=True) tester.testDone() tester.groupDone() tester.startGroup('XUpdate exceptions') uri = OsPathToUri('xupdate-test-src-2.xml', attemptAbsolute=True) isrc = InputSource.DefaultFactory.fromString(src_2, uri) src = srcReader(isrc) from Ft.Xml.XUpdate import XUpdateException for name, xuSrc, expected in [ ('missing version attr', EXCEPTION_XUP_1, XUpdateException.NO_VERSION), ('missing select attr', EXCEPTION_XUP_2, XUpdateException.NO_SELECT), ('invalid select attr', EXCEPTION_XUP_3, XUpdateException.INVALID_SELECT), ('syntax error', EXCEPTION_XUP_4, XUpdateException.SYNTAX_ERROR), ('missing test attr', EXCEPTION_XUP_5, XUpdateException.NO_TEST), ('unrecognized instruction', EXCEPTION_XUP_6, XUpdateException.UNRECOGNIZED_INSTRUCTION), ]: tester.startTest(name) uri = OsPathToUri('xupdate-test-xup-' + quote(name) + '.xml', attemptAbsolute=True) isrc = InputSource.DefaultFactory.fromString(xuSrc, uri) xu = xureader.fromSrc(isrc) tester.testException(processor.execute, (src, xu), XUpdateException, {'errorCode': expected}) tester.testDone() tester.groupDone() return
def TestTree(): from sys import getrefcount doc = Domlette.Document() assert getrefcount(doc) == 2, "Document Creation" PI = Domlette.ProcessingInstruction( doc, 'xml-stylesheet', 'href="addr_book1.xsl" type="text/xml"') doc.appendChild(PI) assert getrefcount(doc) == 3, "PI Creation" docelem = Domlette.Element(doc, None, 'docelem') doc.appendChild(docelem) assert getrefcount(doc) == 4, "Element Creation" nsdecl = Domlette.Attr(doc, XMLNS_NAMESPACE, 'xmlns:ft') nsdecl.value = 'http://fourthought.com' docelem.setAttributeNodeNS(nsdecl) assert getrefcount(doc) == 5, "NSDecl Creation" text = Domlette.Text(doc, '\n ') docelem.appendChild(text) assert getrefcount(doc) == 6, "First Text" CHILD = Domlette.Element(doc, None, 'child') docelem.appendChild(CHILD) assert getrefcount(doc) == 7, "First Child" ATTR = Domlette.Attr(doc, None, 'foo') ATTR.value = 'bar' CHILD.setAttributeNodeNS(ATTR) assert getrefcount(doc) == 8, "First Child Attr" TEXT = Domlette.Text(doc, 'Some Text') CHILD.appendChild(TEXT) assert getrefcount(doc) == 9, "First Child Text" text = Domlette.Text(doc, "\n ") docelem.appendChild(text) assert getrefcount(doc) == 10, "Second Text" COMMENT = Domlette.Comment(doc, 'A comment') docelem.appendChild(COMMENT) assert getrefcount(doc) == 11, "Comment" text = Domlette.Text(doc, '\n ') docelem.appendChild(text) assert getrefcount(doc) == 12, "Third Text" NS_CHILD = Domlette.Element(doc, 'http://fourthought.com', 'ft:nschild') docelem.appendChild(NS_CHILD) assert getrefcount(doc) == 13, "Second Child" NS_ATTR = Domlette.Attr(doc, 'http://fourthought.com', 'ft:foo') NS_ATTR.value = 'nsbar' NS_CHILD.setAttributeNodeNS(NS_ATTR) assert getrefcount(doc) == 14, "Second Child Attr" text = Domlette.Text(doc, 'Some More Text') NS_CHILD.appendChild(text) assert getrefcount(doc) == 15, "Second Child Text" text = Domlette.Text(doc, '\n ') docelem.appendChild(text) assert getrefcount(doc) == 16, "Fourth Text" APPEND_CHILD = Domlette.Element(doc, None, 'appendChild') docelem.appendChild(APPEND_CHILD) assert getrefcount(doc) == 17, "Append Child" text = Domlette.Text(doc, '\n ') docelem.appendChild(text) assert getrefcount(doc) == 18, "Fifth Text" return doc
def XsltTest(tester, sourceXml, stylesheets, expected, compareFunc=None, ignorePis=1, topLevelParams=None, extensionModules=None, exceptionClass=XsltException, exceptionCode=None, stylesheetInputFactory=None, documentInputFactory=None, stylesheetAltUris=None, title='', funcArgs=None): """ Common function to perform an XSLT transformation and compare the results through the tester. title is a short name that describes the test. tester is an Ft.Lib.TestSuite.Tester instance. sourceXml is a FileInfo instance for the source document. stylesheets is a list of FileInfo instances for the stylesheet(s). expected is a string to compare the actual transformation result to. compareFunc is a cmp()-like function to use to do the comparison. It defaults to whatever the tester's default is; usually cmp(). funcArgs is a dictionary of keyword arguments to pass to the comparison function, if it accepts keyword arguments. ignorePis, topLevelParams, extensionModules, stylesheetAltUris are as documented in Ft.Xml.Xslt.Processor.Processor. exceptionCode is the expected exception code, if the test is intended to generate an exception. documentInputFactory, stylesheetInputFactory are InputSource factories to use when resolving references to external URIs from within the source document or stylesheet(s), respectively. Defaults for both are Ft.Xml.InputSource.DefaultFactory. """ # reset the counter for generate-id g_idmap.clear() if not title: title = 'Source %(source)s' % (tester.test_data) tester.startTest(title) # Create the processor processor = Processor.Processor(stylesheetAltUris=stylesheetAltUris) processor.registerExtensionModules([__name__]) if extensionModules: processor.registerExtensionModules(extensionModules) # Setup document input for the processor factory = documentInputFactory or InputSource.DefaultFactory reader = Domlette._Reader(tester.test_data['module'].NonvalParse, kwargs={'readExtDtd': READ_EXTERNAL_DTD}) reader.inputSourceFactory = factory processor.setDocumentReader(reader) # Do the transformation try: # Add the stylesheets to the processor factory = stylesheetInputFactory or InputSource.DefaultFactory for stylesheet in stylesheets: processor.appendStylesheet(stylesheet.toInputSource(factory)) result = processor.run(sourceXml.toInputSource(factory), ignorePis=ignorePis, topLevelParams=topLevelParams) except exceptionClass, exception: if exceptionCode is None: # No exception was expected estr = _PrettifyException(exceptionClass, exception.errorCode) tester.exception('Unexpected exception ' + estr) else: # Compare the exception result expected = _PrettifyException(exceptionClass, exceptionCode) compared = _PrettifyException(exceptionClass, exception.errorCode) tester.compare(expected, compared, stackLevel=2)
def test_strip_elements(tester, domMod): tester.startGroup("Strip Elements") tester.startTest("Strip Elements") src = "<ft:foo xmlns:ft='http://fourthought.com' xmlns:ft2='http://foo.com'><ft:bar> </ft:bar><ft:bar> F </ft:bar><ft:baz> Bar1 </ft:baz><ft2:bar> </ft2:bar><ft2:baz> Bar2 </ft2:baz><bar> </bar><baz> Bar3 </baz></ft:foo>" stripElements = [(None, 'bar', 1), ('http://fourthought.com', 'bar', 1), ('http://foo.com', '*', 1)] isrc = InputSource.DefaultFactory.fromString(src, BASE_PATH, stripElements=stripElements) dom = domMod.NonvalParse(isrc) tester.compare(None, dom.documentElement.childNodes[0].firstChild) tester.compare(" F ", dom.documentElement.childNodes[1].firstChild.data) tester.compare(" Bar1 ", dom.documentElement.childNodes[2].firstChild.data) tester.compare(None, dom.documentElement.childNodes[3].firstChild) tester.compare(" Bar2 ", dom.documentElement.childNodes[4].firstChild.data) tester.compare(None, dom.documentElement.childNodes[5].firstChild) tester.compare(" Bar3 ", dom.documentElement.childNodes[6].firstChild.data) tester.testDone() tester.startTest("Strip Elements with xml:space") src = """\ <svg xml:space="preserve" width="1000" height="1000" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <desc>Salary Chart</desc> <g style='stroke:#000000;stroke-width:1;font-family:Arial;font-size:16'> <xsl:for-each select="ROWSET/ROW"> <xsl:call-template name="drawBar" xml:space="default"> <xsl:with-param name="rowIndex" select="position()"/> <xsl:with-param name="ename" select="ENAME"/> <xsl:with-param name="sal" select="number(SAL)"/> </xsl:call-template> </xsl:for-each> </g> </svg>""" expected = """<?xml version="1.0" encoding="UTF-8"?> <svg xml:space="preserve" width="1000" height="1000" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <desc>Salary Chart</desc> <g style='stroke:#000000;stroke-width:1;font-family:Arial;font-size:16'> <xsl:for-each select="ROWSET/ROW"> <xsl:call-template name="drawBar" xml:space="default"><xsl:with-param name="rowIndex" select="position()"/><xsl:with-param name="ename" select="ENAME"/><xsl:with-param name="sal" select="number(SAL)"/></xsl:call-template> </xsl:for-each> </g> </svg>""" src = """<?xml version="1.0" encoding="UTF-8"?> <element xml:space="preserve"> <element> <!-- surrounding WS should be preserved --> </element> </element>""" stripElements = [(None, '*', True)] isrc = InputSource.DefaultFactory.fromString(src, BASE_PATH, stripElements=stripElements) dom = domMod.NonvalParse(isrc) sio = cStringIO.StringIO() Domlette.Print(dom, sio) actual = sio.getvalue() tester.compare(src, actual, func=TreeCompare.TreeCompare) tester.testDone() tester.groupDone() return
def test_nonvalidating_reader(tester, domMod): tester.startGroup("non-Validating Reader") tester.startTest("Simple XML") src = InputSource.DefaultFactory.fromString(SMALL_XML, BASE_PATH) doc = domMod.NonvalParse(src) #Test a few of the nodes tester.compare(2, len(doc.childNodes)) tester.compare(Node.PROCESSING_INSTRUCTION_NODE, doc.childNodes[0].nodeType) tester.compare("xml-stylesheet", doc.childNodes[0].target) tester.compare('href="addr_book1.xsl" type="text/xml"', doc.childNodes[0].data) tester.compare(Node.ELEMENT_NODE, doc.childNodes[1].nodeType) tester.compare('docelem', doc.childNodes[1].nodeName) tester.compare(None, doc.childNodes[1].namespaceURI) tester.compare(None, doc.childNodes[1].prefix) tester.compare(doc.childNodes[1], doc.documentElement) tester.compare(9, len(doc.documentElement.childNodes)) tester.compare(1, len(doc.documentElement.attributes.keys())) tester.compare(('http://www.w3.org/2000/xmlns/', 'ft'), doc.documentElement.attributes.keys()[0]) tester.compare('http://fourthought.com', doc.documentElement.attributes.values()[0].value) tester.compare(1, len(doc.documentElement.childNodes[1].attributes.keys())) tester.compare((None, 'foo'), doc.documentElement.childNodes[1].attributes.keys()[0]) tester.compare( 'bar', doc.documentElement.childNodes[1].attributes.values()[0].value) tester.compare('Some Text', doc.documentElement.childNodes[1].childNodes[0].data) tester.compare('http://fourthought.com', doc.documentElement.childNodes[5].namespaceURI) tester.compare('ft', doc.documentElement.childNodes[5].prefix) tester.compare(1, len(doc.documentElement.childNodes[5].attributes.keys())) tester.compare(('http://fourthought.com', 'foo'), doc.documentElement.childNodes[5].attributes.keys()[0]) tester.compare( 'nsbar', doc.documentElement.childNodes[5].attributes.values()[0].value) tester.testDone() tester.startTest("Parse nasty XML") src = InputSource.DefaultFactory.fromString(LARGE_XML, BASE_PATH) doc = domMod.NonvalParse(src) tester.testDone() tester.startTest( "Document with general entity defined in external subset (parse method 1)" ) source_1 = GREETING isrc = InputSource.DefaultFactory.fromString(source_1, BASE_PATH) dom = domMod.NonvalParse(isrc, readExtDtd=1) stream = cStringIO.StringIO() Domlette.Print(dom, stream) expected_1 = """\ <?xml version="1.0" encoding="UTF-8"?> <greeting>hello world</greeting> """ tester.compare(expected_1, stream.getvalue(), func=CompareXml) tester.testDone() # same as previous test but going through Ft.Xml.Domlette tester.startTest( "Document with general entity defined in external subset (parse method 2)" ) source_1 = GREETING isrc = InputSource.DefaultFactory.fromString(source_1, BASE_PATH) from Ft.Xml.Domlette import NonvalidatingReaderBase reader = NonvalidatingReaderBase() reader.kwargs['readExtDtd'] = 1 dom = reader.parse(isrc) stream = cStringIO.StringIO() Domlette.Print(dom, stream) expected_1 = """\ <?xml version="1.0" encoding="UTF-8"?> <greeting>hello world</greeting> """ tester.compare(expected_1, stream.getvalue(), func=CompareXml) tester.testDone() tester.groupDone()
def test_extent_xinclude(tester, domMod): tester.startGroup("Reader + External Entities + XInclude") SRC_1 = """\ <?xml version='1.0'?> <!DOCTYPE x [ <!ENTITY inc SYSTEM "include1.xml"> ]> <x> &inc; </x>""" expected_1 = """<?xml version='1.0' encoding='UTF-8'?><x> <foo xml:base="%s"/> </x>""" % Uri.Absolutize("include1.xml", BASE_PATH) tester.startTest("External entity") src = InputSource.DefaultFactory.fromString(SRC_1, BASE_PATH) doc = domMod.NonvalParse(src) stream = cStringIO.StringIO() Domlette.Print(doc, stream) tester.compare(expected_1, stream.getvalue(), func=TreeCompare.TreeCompare) tester.testDone() SRC_2 = """\ <?xml version='1.0'?> <x xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="include1.xml"/> </x>""" expected_2 = """<?xml version='1.0' encoding='UTF-8'?> <x xmlns:xi='http://www.w3.org/2001/XInclude'> <foo xml:base="%s"/> </x>""" % Uri.Absolutize("include1.xml", BASE_PATH) tester.startTest("Basic XInclude") src = InputSource.DefaultFactory.fromString(SRC_2, BASE_PATH) doc = domMod.NonvalParse(src) stream = cStringIO.StringIO() Domlette.Print(doc, stream) tester.compare(expected_2, stream.getvalue(), func=TreeCompare.NoWsTreeCompare) tester.testDone() SRC_3 = """\ <?xml version='1.0'?> <x xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="include2.xml"/> </x>""" expected_3 = """<?xml version='1.0' encoding='UTF-8'?> <x xmlns:xi='http://www.w3.org/2001/XInclude'> <foo xml:base="%s"> <foo xml:base="%s"/> </foo> </x> """ % (Uri.Absolutize("include2.xml", BASE_PATH), Uri.Absolutize("include1.xml", BASE_PATH)) tester.startTest("Recursive XInclude") src = InputSource.DefaultFactory.fromString(SRC_3, BASE_PATH) doc = domMod.NonvalParse(src) stream = cStringIO.StringIO() Domlette.Print(doc, stream) tester.compare(expected_3, stream.getvalue(), func=TreeCompare.NoWsTreeCompare) tester.testDone() SRC_4 = """\ <?xml version='1.0'?> <x xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="include2.xml" parse='text'/> </x>""" from test_xinclude import LINESEP expected_4 = """<?xml version='1.0' encoding='UTF-8'?> <x xmlns:xi='http://www.w3.org/2001/XInclude'> <?xml version='1.0' encoding='utf-8'?>%(linesep)s<foo xmlns:xi="http://www.w3.org/2001/XInclude">%(linesep)s <xi:include href="include1.xml"/>%(linesep)s</foo> </x> """ % { 'linesep': LINESEP } tester.startTest("XInclude text attribute") src = InputSource.DefaultFactory.fromString(SRC_4, BASE_PATH) doc = domMod.NonvalParse(src) stream = cStringIO.StringIO() Domlette.Print(doc, stream) tester.compare(expected_4, stream.getvalue(), func=TreeCompare.TreeCompare) tester.testDone() tester.groupDone() return
def visit(self, context, node, preserveSpace): #FIXME: We should improve this function from this ugly-ass #switch thingie to dynamic dispatch if node.nodeType == Node.ELEMENT_NODE: xml_space = node.getAttributeNS(XML_NAMESPACE, 'space') if xml_space == 'preserve': preserveSpace = 1 elif xml_space == 'default': preserveSpace = 0 # else, no change if node.namespaceURI != XUPDATE_NS: self.writers[-1].startElement(node.nodeName, node.namespaceURI) # Process the attributes oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) for attr in node.attributes.values(): value = self.parseAVT(attr.value) value = value.evaluate(context) self.writers[-1].attribute(attr.nodeName, value, attr.namespaceURI) context.processorNss = oldNss # Now the children for child in node.childNodes: context = self.visit(context, child, preserveSpace) self.writers[-1].endElement(node.nodeName) return context # XUpdate elements try: restoreGraphContext = False graphURI = node.getAttributeNS(EMPTY_NAMESPACE, u'to-graph') if graphURI: graphURI = self.parseAVT(graphURI) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) graphURI = graphURI.evaluate(context) context.processorNss = oldNss context.node.ownerDocument.pushContext(graphURI) restoreGraphContext = True if node.localName == 'modifications': for n in node.childNodes: self.visit(context, n, preserveSpace) elif node.localName == 'remove': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') #import sys #print >>sys.stderr, 'removing', select if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if nodeset: #change from 4Suite -- why did it only delete the first node in the nodeset? #that's not in the spec or very intuitive #refnode = nodeset[0] for refnode in nodeset: if refnode.nodeType == Node.ATTRIBUTE_NODE: parent = refnode.ownerElement parent.removeAttributeNode(refnode) else: parent = refnode.parentNode if parent is None: parent = refnode.ownerDocument parent.removeChild(refnode) context.processorNss = oldNss elif node.localName in ['insert-after', 'insert-before']: select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() if node.localName == 'insert-before': refnode.parentNode.insertBefore(result, refnode) elif node.localName == 'insert-after': # if arg 2 is None, insertBefore behaves like appendChild refnode.parentNode.insertBefore( result, refnode.nextSibling) context.processorNss = oldNss elif node.localName == 'element': name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.writers[-1].startElement(name, namespace) for child in node.childNodes: context = self.visit(context, child, preserveSpace) self.writers[-1].endElement(name) context.processorNss = oldNss elif node.localName == 'attribute': name = node.getAttributeNS(EMPTY_NAMESPACE, 'name') if not name: raise XUpdateException(XUpdateException.NO_NAME) _name = self.parseAVT(name) namespace = node.getAttributeNS(EMPTY_NAMESPACE, 'namespace') _namespace = self.parseAVT(namespace) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) name = _name.evaluate(context) namespace = _namespace and _namespace.evaluate(context) (prefix, local) = SplitQName(name) if not namespace: if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE self.pushStringResult() try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() self.writers[-1].attribute(name, result, namespace) context.processorNss = oldNss elif node.localName == 'append': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) _select = self.parseExpression(select) child = node.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()' _child = self.parseExpression(child) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException(XUpdateException.INVALID_SELECT, select) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() size = len(refnode.childNodes) con = Context.Context(refnode, 1, size, processorNss={'xupdate': XUPDATE_NS}) # Python lists is 0-indexed counting, node-sets 1-indexed position = int( Conversions.NumberValue(_child.evaluate(con))) if position >= size: refnode.appendChild(result) else: refnode.insertBefore(result, refnode.childNodes[position]) context.processorNss = oldNss elif node.localName == 'replace': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) refnode = nodeset[0] self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() if refnode.nodeType == Node.ATTRIBUTE_NODE: owner = refnode.parentNode owner.removeAttributeNode(refnode) owner.setAttributeNodeNS(result) else: refnode.parentNode.replaceChild(result, refnode) context.processorNss = oldNss elif node.localName == 'update': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) refnode = nodeset[0] if refnode.nodeType == Node.ATTRIBUTE_NODE: self.pushStringResult() try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() refnode.nodeValue = refnode.value = result else: self.pushDomResult(refnode.ownerDocument) try: for child in node.childNodes: context = self.visit(context, child, preserveSpace) finally: result = self.popResult() while refnode.firstChild: #print 'remove', id(refnode), id(refnode.firstChild), len(refnode.childNodes) refnode.removeChild(refnode.firstChild) refnode.appendChild(result) context.processorNss = oldNss
sys.stderr.flush() return try: xml_reader = Domlette.NonvalidatingReader xupdate_reader = XUpdate.Reader() processor = XUpdate.Processor() source_doc = xml_reader.parse(source_isrc) CloseStream(source_isrc, quiet=True) compiled_xupdate = xupdate_reader.fromSrc(xupdate_isrc) CloseStream(xupdate_isrc, quiet=True) processor.execute(source_doc, compiled_xupdate) Domlette.Print(source_doc, stream=out_file) except Exception, e: import traceback traceback.print_exc(1000, sys.stderr) raise try: if out_file.isatty(): out_file.flush() sys.stderr.write('\n') else: out_file.close() except (IOError, ValueError): pass
def Test(tester): tester.startGroup('XML and TR9401 Catalogs') tester.startTest('Parse an XML Catalog supplied via a URI') cat_path = os.path.join('Xml', 'Core', 'xcatalog.xml') cat_uri = Uri.OsPathToUri(cat_path, attemptAbsolute=1) cat = Catalog(cat_uri) tester.testDone() tf_path = os.path.join('Xml', 'Core', 'include1.xml') try: fd = open(tf_path) orig = fd.read() fd.close() except: fd.close() tester.warning('Could not read test file; skipping resolution tests.') return tester.startTest('Parse an XML Catalog supplied via an InputSource') fd = open(cat_path, 'rb') cat_data = fd.read() fd.close() isrc = NoCatalogFactory.fromString(cat_data, cat_uri) cat = Catalog() cat.isrc = isrc cat.parse() tester.testDone() # The catalog object should map 'urn:bogus:include1.xml' to # 'include1.xml' relative to the catalog's base URI. tester.startTest('Resolve a relative URI reference in the catalog (1)') expected = Uri.Absolutize('include1.xml', cat_uri) tester.compare(expected, cat.uris['urn:bogus:include1.xml']) tester.testDone() # The catalog object should map 'urn:bogus:include1-from-parent.xml' # to 'Core/include1.xml' relative to the catalog's base URI. tester.startTest('Resolve a relative URI reference in the catalog (2)') expected = Uri.Absolutize('Core/include1.xml', cat_uri) tester.compare(expected, cat.uris['urn:bogus:include1-from-parent.xml']) tester.testDone() # Same as above but we'll change the base URI of the catalog and # see if the results are still correct tester.startTest('Resolve a relative URI reference in the catalog (3)') alt_cat_path = os.path.join('Xml', 'xcatalog.xml') alt_cat_uri = Uri.OsPathToUri(alt_cat_path, attemptAbsolute=1) alt_cat_isrc = NoCatalogFactory.fromString(cat_data, alt_cat_uri) alt_cat = Catalog() alt_cat.isrc = alt_cat_isrc alt_cat.uri = alt_cat_uri alt_cat.parse() expected = Uri.Absolutize('Core/include1.xml', alt_cat_uri) tester.compare(expected, alt_cat.uris['urn:bogus:include1-from-parent.xml']) tester.testDone() # Make sure the default catalog exists and isn't empty tester.startTest('4Suite default catalog exists') from Ft.Xml.Catalog import FT_CATALOG entries = FT_CATALOG.publicIds or FT_CATALOG.uris tester.compare(True, len(entries) > 0) tester.testDone() # A test of catalog support in Ft.Xml.InputSource # (actually try to resolve a document URI with a catalog) tester.startTest( 'Resolve doc via InputSource w/Catalog containing rel. URI (1)') factory = InputSourceFactory(catalog=cat) isrc = factory.fromUri('urn:bogus:include1.xml') data = isrc.read() isrc.close() tester.compare(orig, data) tester.testDone() # A test of catalog support in Ft.Xml.InputSource # (same as previous, just with the different catalog base URI) tester.startTest( 'Resolve doc via InputSource w/Catalog containing rel. URI (2)') factory = InputSourceFactory(catalog=alt_cat) isrc = factory.fromUri('urn:bogus:include1-from-parent.xml') data = isrc.read() isrc.close() tester.compare(orig, data) tester.testDone() # A test of catalog support in Ft.Xml.InputSource # and resolving all combinations of Public and System IDs tester.startTest('Resolve ext. entities w/Catalog') xml_uri = Uri.Absolutize('test_catalog_INTERNAL.xml', cat_uri) factory = InputSourceFactory(catalog=cat) isrc = factory.fromString(XML_1, xml_uri) doc = Domlette.NonvalidatingReader.parse(isrc) st = cStringIO.StringIO() Domlette.Print(doc, stream=st) tester.compare(XML_EXPECTED_1, st.getvalue(), func=TreeCompare) tester.testDone() tester.groupDone() return
refnode.appendChild(result) context.processorNss = oldNss elif node.localName == 'rename': select = node.getAttributeNS(EMPTY_NAMESPACE, u'select') if not select: raise XUpdateException(XUpdateException.NO_SELECT) try: _select = self.parseExpression(select) except SyntaxError, e: raise SyntaxError("Select Expression %s: %s" % (select, str(e))) oldNss = context.processorNss context.processorNss = Domlette.GetAllNs(node) nodeset = _select.evaluate(context) if not nodeset: raise XUpdateException( XUpdateException.INVALID_SELECT, node.getAttributeNS(EMPTY_NAMESPACE, u'select')) Domlette.XmlStrStrip(node.firstChild.data) new_name = node.firstChild.data.strip() (prefix, local) = SplitQName(new_name) if prefix: namespace = context.processorNss[prefix] else: namespace = EMPTY_NAMESPACE