def _prepareDocument(self, record): doc = record if isinstance(record, str): doc = XMLFragment(record) root = doc.getRootElement() # Add the date if it's not already there. if 0 == len(doc.xpathEval("//pubDate")): date = time.time() # ISO8601 Date # TODO this shouldn't really use localtime as the ISO8601 date should be GMT. Just not sure how to # convert the time using XSL-T otherwise. pubDate = root.newChild( None, "pubDate", time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(date)) + "-07:00" ) pubDate.setProp("seconds", str(date)) # Set the id for the post # TODO: maybe this would be better as meta-data or should at least # be in a namespace # This call will also mark the database as modified # TODO: see if there's a better way. recordID = self.getNextID() root.setProp("id", str(recordID)) return (doc, recordID)
def _increment(self, txn, record, params): self.log.debug("increment called") targetPath = params.getValue("param[@name='target-path']") keyPath = params.getValue("param[@name='key-path']") # We get the key data that we should look for in the related documents. targetID = record.getValue(keyPath) try: self.log.debug("increment retrieving record " + targetID) target = XMLFragment(self.getRecord(txn, targetID)) self.log.debug("increment record retrieved") result = target.getSingle(targetPath) # See whether we should update the count or add the element if result != None: count = int(result.getContent()) result.setContent(str(count + 1)) else: nodeName = targetPath.split("/")[-1] target.getRootElement().newChild(None, nodeName, "1") self.log.debug("increment saving modified record") self.updateRecord(txn, targetID, target.serialize()) except NotFoundError: self.log.warn("increment called for non-existent target")
def testGetSingle(self): doc = libxml2.parseDoc(testEntry) fragment = XMLFragment(doc) self.assertEqual(fragment.getSingle("/item/title").getFragment().content, "Test Post 1") self.assertEqual(fragment.getSingle("/item/category").getFragment().content, "XML") self.assertEqual(fragment.getSingle("/item/no-exist"), None)
def runTransform(self, data, stylesheetName, arg, defaultStylesheet=""): # Find the actual location for the stylesheet stylesheet = self.locateStylesheet(stylesheetName) if stylesheet == None: # if the stylesheet wasn't found try for the default style if defaultStylesheet != "": stylesheet = self.locateStylesheet(defaultStylesheet) if stylesheet == None: # TODO this should throw an exception self.log.error("Stylesheet implementation could not be found for %s" % stylesheetName) return "" resultXML = "" # Parse the stylesheet self.mutex.acquire() try: from time import clock # TODO: room for optimization, should also make sure it's OK for # libxslt to run with multiple threads. style = None try: starttime = clock() styledoc = libxml2.parseFile(stylesheet) style = libxslt.parseStylesheetDoc(styledoc) doc = XMLFragment(data) self.log.debug(str(clock() - starttime) + " seconds for xsl parse") except: self.log.exception("Error parsing stylesheet %s" % stylesheet) raise starttime = clock() result = XMLFragment( style.applyStylesheet( doc.getFragment(), {"arg": '"' + arg + '"', "site_id": '"' + self.configValue("/blog/id") + '"'} ) ) if not (result.serialize() == '<?xml version="1.0"?>\n'): resultXML = style.saveResultToString(result.getFragment()) self.log.debug(str(clock() - starttime) + " seconds for xsl execution") finally: if style != None: style.freeStylesheet() self.mutex.release() # styledoc.freeDoc() # result.freeDoc() return resultXML
def _checkBlacklist(self, content, message): # Check for a direct string, we're just interested in the hostname so # we need to clean it up. if (self._checkURL(content, message) == 0): # No match on a plain string so we need to try parsing as XML to # see there are any embedded URLs try: contentDoc = XMLFragment("<wrap>" + content + "</wrap>") urls = contentDoc.xpathEval("//@href") for url in urls: self._checkURL(url.content, message) except: # if this fails then we don't worry because it will get rejected # anyway. pass
def _cascadeDeletes(self, txn, record, params): targetRoot = params.getValue("param[@name='target-root']") fromKey = params.getValue("param[@name='from-key']") targetKey = params.getValue("param[@name='target-key']") # We get the key data that we should look for in the related documents. relation = record.getValue("/%s/%s" % (record.getRootElement().name, fromKey)) if relation != "": # Now build the query to select the ids for the target documents query = "/%s[%s=%s]/@id" % (targetRoot, targetKey, relation) related = XMLFragment(self.xpathQuery(txn, query)) content = related.getRootElement().content.strip() if content != "": for id in content.split("\n"): try: self.deleteRecord(txn, id) except NotFoundError: self.log.warn("_cascadeDeletes: Deleting %s, but it's already gone" % id)
def _decrement(self, txn, record, params): self.log.debug("decrement called") targetPath = params.getValue("param[@name='target-path']") keyPath = params.getValue("param[@name='key-path']") # We get the key data that we should look for in the related documents. targetID = record.getValue(keyPath) try: target = XMLFragment(self.getRecord(txn, targetID)) result = target.getSingle(targetPath) if result != None: count = int(result.getContent()) - 1 if count < 0: count = 0 result.setContent(str(count)) self.updateRecord(txn, targetID, target.serialize()) except NotFoundError: self.log.warn("decrement called for non-existent target")
def _applyTriggers(self, txn, action, record): if isinstance(record, str): record = XMLFragment(record) rootName = record.getRootElement().name self.log.debug("_applyTriggers: handling %s for type %s" % (action, rootName)) # See if there are any reference triggers for this type of item and this # action query = "/datatypes/datatype/relation[@from-type = '%s']/trigger[on = '%s']" query = query % (rootName, action) self.log.debug("_applyTriggers: looking for triggers with query %s" % query) self._runTriggers(txn, query, record) # Handle any references for actions that should occur for the same # datatype query = "/datatypes/datatype[@root='%s']/trigger[on='%s']" query = query % (rootName, action) self.log.debug("_applyTriggers: looking for triggers with query %s" % query) self._runTriggers(txn, query, record)
def testGetValue(self): fragment = XMLFragment(testEntry) self.assertEqual(fragment.getValue("/item/title"), "Test Post 1") self.assertEqual(fragment.getValue("/item/category"), "XML") self.assertEqual(fragment.getValue("/item/category", "default"), "XML") self.assertEqual(fragment.getValue("/item/no-exist"), "") self.assertEqual(fragment.getValue("/item/no-exist", "default"), "default") # Test relative paths against nodes fragment2 = fragment.getSingle("/item") self.assertEqual(fragment2.getValue("title"), "Test Post 1") self.assertEqual(fragment2.getValue("category"), "XML") self.assertEqual(fragment2.getValue("no-exist", "default"), "default")
def queryDocument(self, content, xpath): doc = XMLFragment(content) result = XMLFragment() results = doc.xpathEval(xpath) if len(results) > 0: root = result.getFragment().newChild(None, "results", None) for item in results: item.unlinkNode() item.reconciliateNs(doc.getDocument()) content = item.serialize() root.addChild(item) return result.serialize() else: return '<?xml version="1.0"?><results/>'
def testAddNode(self): # Test creating a new document doc = XMLFragment() doc.addNode("/root") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root/>\n') # Test adding on a child node doc.addNode("/root/child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/></root>\n') # Test creating the parent and child in one step. doc = XMLFragment() doc.addNode("/root/child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/></root>\n') # Test creating the parent and child in one step with some content doc = XMLFragment() doc.addNode("/root/child", "text") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child>text</child></root>\n') # Now add another level doc.addNode("/root/child/subchild") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child>text<subchild/></child></root>\n') # Add a second child with the same name doc.addNode("/root/child", "text") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child>text<subchild/></child><child>text</child></root>\n') # Create two children then add a subchild to each doc = XMLFragment() doc.addNode("/root/child") doc.addNode("/root/child") doc.addNode("/root/child/subchild") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child><subchild/></child><child><subchild/></child></root>\n') # Create two children then add a subchild to just the second child doc = XMLFragment() doc.addNode("/root/child") doc.addNode("/root/child") doc.addNode("/root/child[2]/subchild") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><child><subchild/></child></root>\n') # Test adding with an anonymouse root node doc = XMLFragment() doc.addNode("/root/child") doc.addNode("/node()/child") doc.addNode("/node()/child[2]/subchild") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><child><subchild/></child></root>\n') # add an attribute to the first child doc.addNode("/root/child[1]/@attr", "text") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child attr="text"/><child><subchild/></child></root>\n') # add a string that should be parsed as markup doc = XMLFragment() doc.addNode("/root/child") doc.addNode("/root/markup", "<test>text</test>", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><markup><test>text</test></markup></root>\n') # add a pre-parsed node to the document doc = XMLFragment() doc.addNode("/root/child") markup = libxml2.parseDoc("<test>text</test>") doc.addNode("/root/markup", markup.getRootElement()) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><markup><test>text</test></markup></root>\n')
def testInsertNodeAfter(self): # create a tree and then insert a new empty node doc = XMLFragment() doc.addNode("/root/child") doc.insertNodeAfter("/root/child", "newChild") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><newChild/></root>\n') # create a tree and then insert a new node with content doc = XMLFragment() doc.addNode("/root/child") doc.insertNodeAfter("/root/child", "newChild", "text") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><newChild>text</newChild></root>\n') # create a tree and then insert a new node with markup content doc = XMLFragment() doc.addNode("/root/child") doc.insertNodeAfter("/root/child", "newChild", "<b>text</b>", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/><newChild><b>text</b></newChild></root>\n')
def testRemoveNodeNs(self): namespaces = {'t': "test", 's': "test2"} # Test deleting a node that's in a namespace doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/root/t:child") doc.removeNode("/root/t:child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root xmlns:t="test"/>\n') # create a tree then remove the second child doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/root/t:child") doc.addNode("/root/t:child") doc.removeNode("/root/t:child[2]") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root xmlns:t="test"><t:child/></root>\n')
def testRemoveNode(self): # create a tree then remove the child doc = XMLFragment() doc.addNode("/root/child") doc.removeNode("/root/child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root/>\n') # create a tree then remove the second child doc = XMLFragment() doc.addNode("/root/child") doc.addNode("/root/child") doc.removeNode("/root/child[2]") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child/></root>\n')
def testUpdateNode(self): # create a tree and then set a node to a new value doc = XMLFragment() doc.addNode("/root/child") doc.updateNode("/root/child", "text") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child>text</child></root>\n') # add another child and then update both to the same value doc.addNode("/root/child") doc.updateNode("/root/child", "newText") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child>newText</child><child>newText</child></root>\n') # Now just update the second child. doc.updateNode("/root/child[2]", "text") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child>newText</child><child>text</child></root>\n') # Now update an attribute doc.addNode("/root/child[1]/@attr", "text") doc.updateNode("/root/child[1]/@attr", "newText") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child attr="newText">newText</child><child>text</child></root>\n') # change a node to a string that should be parsed as markup doc = XMLFragment() doc.addNode("/root/child", "text") doc.updateNode("/root/child", "<test>text</test>", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child><test>text</test></child></root>\n') # replace the content of a node with more then one child doc = XMLFragment() doc.addNode("/root/child", "<test>text</test><test>text2</test>", 1) doc.updateNode("/root/child", "<test>text3</test><test>text4</test>", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child><test>text3</test><test>text4</test></child></root>\n') # add a pre-parsed node to the document doc = XMLFragment() doc.addNode("/root/child") markup = libxml2.parseDoc("<test>text</test>") doc.updateNode("/root/child", markup.getRootElement()) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child><test>text</test></child></root>\n') # Update a node that doesn't already exist. doc = XMLFragment() markup = libxml2.parseDoc("<test>text</test>") doc.updateNode("/root/child", markup.getRootElement()) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<root><child><test>text</test></child></root>\n')
def testAddNodeNs(self): # Check creating the root in a namespace doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/t:root") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test"/>\n') # now add a child in the same namespace doc.addNode("/t:root/t:child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test"><t:child/></t:root>\n') # now add a child in no namespace doc.addNode("/t:root/child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test"><t:child/><child/></t:root>\n') # now add a child in a different namespace doc.addNode("/t:root/child/s:child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test"><t:child/><child xmlns:s="test2"><s:child/></child></t:root>\n') # Check creating the root in a namespace with some content doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/t:root", "test") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test">test</t:root>\n') # Now add a node with no NS and some content doc.addNode("/t:root/child", "test") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test">test<child>test</child></t:root>\n') # Now add some markup that doesn't have any namespaces doc.addNode("/t:root/child/markup", "some <b>content</b> bold", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test">test<child>test<markup>some <b>content</b> bold</markup></child></t:root>\n') # Test combinations of namespaces in markup # Add some markup to a node in a namespace but where the markup has no # namespaces doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/t:root") doc.addNode("/t:root/s:markup", "some <b>content</b> bold", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test" xmlns:s="test2"><s:markup>some <b>content</b> bold</s:markup></t:root>\n') # Add markup that uses namespaces doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/t:root") doc.addNode("/t:root/s:markup", "some <x:b xmlns:x='test3'>content</x:b> bold", 1) self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test" xmlns:s="test2"><s:markup>some <x:b xmlns:x="test3">content</x:b> bold</s:markup></t:root>\n') # Test creation of a deeper tree to make sure we get the proper ns defs doc = XMLFragment() #doc.registerNamespaces(namespaces) doc.addNode("/t:root/t:child/t:child", "test") doc.addNode("/t:root/t:child") self.assertEqual(doc.serialize(), '<?xml version="1.0"?>\n<t:root xmlns:t="test"><t:child><t:child>test</t:child></t:child><t:child/></t:root>\n')