Exemple #1
0
def sendPresence(pytrans, to, fro, show=None, status=None, priority=None, ptype=None, avatarHash=None, nickname=None, payload=[], url=None):
	if ptype in ["subscribe", "subscribed", "unsubscribe", "unsubscribed"]:
		to = internJID(to).userhost()
		fro = internJID(fro).userhost()

	el = Element((None, "presence"))
	el.attributes["to"] = to
	el.attributes["from"] = fro
	if ptype:
		el.attributes["type"] = ptype
	if show:
		s = el.addElement("show")
		s.addContent(utils.xmlify(show))
	if status:
		s = el.addElement("status")
		s.addContent(utils.xmlify(status))
	if priority:
		s = el.addElement("priority")
		s.addContent(priority)
	if url:
		s = el.addElement("x")
		s.attributes["xmlns"] = globals.XOOB
		s = el.addElement("url")
		s.addContent(url)

	if not ptype:
		if avatarHash and not config.disableAvatars and not config.disableVCardAvatars:
			x = el.addElement("x")
			x.attributes["xmlns"] = globals.VCARDUPDATE
			p = x.addElement("photo")
			p.addContent(avatarHash)

		if nickname:
			x = el.addElement("x")
			x.attributes["xmlns"] = globals.VCARDUPDATE
			n = x.addElement("nickname")
			n.addContent(nickname)

		if avatarHash and not config.disableAvatars and not config.disableIQAvatars:
			x = el.addElement("x")
			x.attributes["xmlns"] = globals.XAVATAR
			h = x.addElement("hash")
			h.addContent(avatarHash)

		if nickname and ptype == "subscribe":
			n = el.addElement("nick")
			n.attributes["xmlns"] = globals.NICK
			n.addContent(nickname)

	if payload:
		for p in payload:
			el.addChild(p)

	pytrans.send(el)
Exemple #2
0
    def gotvCard(self, profile, user, vcard, d):
        from glue import aim2jid

        LogEvent(INFO, self.session.jabberID)

        cutprofile = oscar.dehtml(profile)
        nickname = vcard.addElement("NICKNAME")
        nickname.addContent(utils.xmlify(user))
        jabberid = vcard.addElement("JABBERID")
        jabberid.addContent(aim2jid(user))
        desc = vcard.addElement("DESC")
        desc.addContent(utils.xmlify(cutprofile))

        d.callback(vcard)
Exemple #3
0
	def gotAIMvCard(self, profile, user, vcard, d):
		from glue import icq2jid

		LogEvent(INFO, self.session.jabberID)

		cutprofile = oscar.dehtml(profile)
		nickname = vcard.addElement("NICKNAME")
		nickname.addContent(utils.xmlify(user))
		jabberid = vcard.addElement("JABBERID")
		jabberid.addContent(icq2jid(user))
		desc = vcard.addElement("DESC")
		desc.addContent(utils.xmlify(cutprofile))

		d.callback(vcard)
Exemple #4
0
 def setAway(self, awayMessage=None):
     LogEvent(INFO, self.session.jabberID)
     try:
         self.bos.awayResponses = {}
         self.bos.setAway(utils.xmlify(awayMessage))
     except AttributeError:
         #self.alertUser(lang.get("sessionnotactive", config.jid))
         pass
Exemple #5
0
	def setAway(self, awayMessage=None):
		LogEvent(INFO, self.session.jabberID)
		try:
			self.bos.awayResponses = {}
			self.bos.setAway(utils.xmlify(awayMessage))
		except AttributeError:
			#self.alertUser(lang.get("sessionnotactive", config.jid))
			pass
Exemple #6
0
	def gotnovCard(self, profile, user, vcard, d):
		from glue import icq2jid
		LogEvent(INFO, self.session.jabberID)

		nickname = vcard.addElement("NICKNAME")
		nickname.addContent(utils.xmlify(user))
		jabberid = vcard.addElement("JABBERID")
		jabberid.addContent(icq2jid(user))
		desc = vcard.addElement("DESC")
		desc.addContent("User is not online.")

		d.callback(vcard)
def sendMessage(pytrans, to, fro, body=None, mtype=None, delay=None, xhtml=None, nickname=None, receipt=None, mID=None):
	""" Sends a Jabber message """
	LogEvent(INFO)
	el = Element((None, "message"))
	el.attributes["to"] = to
	el.attributes["from"] = fro
	if mID:
		el.attributes["id"] = mID
	else:
		el.attributes["id"] = pytrans.makeMessageID()
	if mtype:
		el.attributes["type"] = mtype

	if delay:
		x = el.addElement("x")
		x.attributes["xmlns"] = globals.XDELAY
		x.attributes["from"] = fro
		x.attributes["stamp"] = delay

	if nickname:
		n = el.addElement("nick")
		n.attributes["xmlns"] = globals.NICK
		n.addContent(nickname)
		
	if receipt:
		r = el.addElement("received")
		r.attributes["xmlns"] = globals.RECEIPTS
	else: # do not send state info in message receipt
		x = el.addElement("x")
		x.attributes["xmlns"] = globals.XEVENT
		composing = x.addElement("composing")
		xx = el.addElement("active")
		xx.attributes["xmlns"] = globals.CHATSTATES
	
	if body:
		b = el.addElement("body")
		b.addContent(utils.xmlify(body))

	if xhtml and not config.disableXHTML:
		try:
			el.addChild(utils.parseText(xhtml))
		except:
			# Hrm, didn't add, we're not going to end the world
			# because of it.
			pass

	pytrans.send(el)
	sendArchive(pytrans, to, fro, body)
Exemple #8
0
def sendMessage(pytrans,
                to,
                fro,
                body,
                mtype=None,
                delay=None,
                xhtml=None,
                nickname=None):
    """ Sends a Jabber message """
    LogEvent(INFO)
    el = Element((None, "message"))
    el.attributes["to"] = to
    el.attributes["from"] = fro
    el.attributes["id"] = pytrans.makeMessageID()
    if mtype:
        el.attributes["type"] = mtype

    if delay:
        x = el.addElement("x")
        x.attributes["xmlns"] = globals.XDELAY
        x.attributes["from"] = fro
        x.attributes["stamp"] = delay

    if nickname:
        n = el.addElement("nick")
        n.attributes["xmlns"] = globals.NICK
        n.addContent(nickname)

    b = el.addElement("body")
    b.addContent(utils.xmlify(body))
    x = el.addElement("x")
    x.attributes["xmlns"] = globals.XEVENT
    composing = x.addElement("composing")
    xx = el.addElement("active")
    xx.attributes["xmlns"] = globals.CHATSTATES

    if xhtml and not config.disableXHTML:
        try:
            el.addChild(utils.parseText(xhtml))
        except:
            # Hrm, didn't add, we're not going to end the world
            # because of it.
            pass

    pytrans.send(el)
    sendArchive(pytrans, to, fro, body)
Exemple #9
0
def sendArchive(pytrans, to, fro, body):
	""" Archive Jabber message if archive element set in config.xml """
	""" send iq xml packet to server specified in archive element """
	""" Configured for DataSink """
	""" THIS IS NOT COMPLIANT WITH JEP-0136 """
	if config.messageArchiveJID:
		LogEvent(INFO) 
		iq = Element((None, "iq"))
		iq.attributes["type"] = "set"
		iq.attributes["from"] = to
		iq.attributes["to"] = config.messageArchiveJID
		myarchive = iq.addElement("archive")
		mymessage = myarchive.addElement("message")
		mymessage.attributes["to"] = to
		mymessage.attributes["from"] = fro
		mybody = mymessage.addElement("body")
		mybody.addContent(utils.xmlify(body))
		pytrans.iq.sendIq(iq)
Exemple #10
0
	def gotvCard(self, usercol):
		from glue import icq2jid

		LogEvent(INFO, self.session.jabberID)

		if usercol != None and usercol.valid:
			vcard = usercol.vcard
			fn = vcard.addElement("FN")
			fn.addContent(utils.xmlify(usercol.first + " " + usercol.last))
			n = vcard.addElement("N")
			given = n.addElement("GIVEN")
			given.addContent(utils.xmlify(usercol.first))
			family = n.addElement("FAMILY")
			family.addContent(utils.xmlify(usercol.last))
			middle = n.addElement("MIDDLE")
			nickname = vcard.addElement("NICKNAME")
			nickname.addContent(utils.xmlify(usercol.nick))
			if usercol.nick:
				#unick,uenc = oscar.guess_encoding(usercol.nick, config.encoding)
				#self.legacyList.updateNickname(usercol.userinfo, unick)
				self.legacyList.updateNickname(usercol.userinfo, usercol.nick)
			bday = vcard.addElement("BDAY")
			bday.addContent(utils.xmlify(usercol.birthday))
			desc = vcard.addElement("DESC")
			desc.addContent(utils.xmlify(usercol.about))
			try:
				c = self.legacyList.ssicontacts[usercol.userinfo]
				desc.addContent(utils.xmlify("\n\n-----\n"+c['lanipaddr']+'/'+c['ipaddr']+':'+"%s"%(c['lanipport'])+' v.'+"%s"%(c['icqprotocol'])))
			except:
				pass
			url = vcard.addElement("URL")
			url.addContent(utils.xmlify(usercol.homepage))

			# Home address
			adr = vcard.addElement("ADR")
			adr.addElement("HOME")
			street = adr.addElement("STREET")
			street.addContent(utils.xmlify(usercol.homeAddress))
			locality = adr.addElement("LOCALITY")
			locality.addContent(utils.xmlify(usercol.homeCity))
			region = adr.addElement("REGION")
			region.addContent(utils.xmlify(usercol.homeState))
			pcode = adr.addElement("PCODE")
			pcode.addContent(utils.xmlify(usercol.homeZIP))
			ctry = adr.addElement("CTRY")
			ctry.addContent(utils.xmlify(usercol.homeCountry))
			# home number
			tel = vcard.addElement("TEL")
			tel.addElement("VOICE")
			tel.addElement("HOME")
			telNumber = tel.addElement("NUMBER")
			telNumber.addContent(utils.xmlify(usercol.homePhone))
			tel = vcard.addElement("TEL")
			tel.addElement("FAX")
			tel.addElement("HOME")
			telNumber = tel.addElement("NUMBER")
			telNumber.addContent(utils.xmlify(usercol.homeFax))
			tel = vcard.addElement("TEL")
			tel.addElement("CELL")
			tel.addElement("HOME")
			number = tel.addElement("NUMBER")
			number.addContent(utils.xmlify(usercol.cellPhone))
			# email
			email = vcard.addElement("EMAIL")
			email.addElement("INTERNET")
			email.addElement("PREF")
			emailid = email.addElement("USERID")
			emailid.addContent(utils.xmlify(usercol.email))

			# work
			adr = vcard.addElement("ADR")
			adr.addElement("WORK")
			street = adr.addElement("STREET")
			street.addContent(utils.xmlify(usercol.workAddress))
			locality = adr.addElement("LOCALITY")
			locality.addContent(utils.xmlify(usercol.workCity))
			region = adr.addElement("REGION")

			region.addContent(utils.xmlify(usercol.workState))
			pcode = adr.addElement("PCODE")
			pcode.addContent(utils.xmlify(usercol.workZIP))
			ctry = adr.addElement("CTRY")
			ctry.addContent(utils.xmlify(usercol.workCountry))

			tel = vcard.addElement("TEL")
			tel.addElement("WORK")
			tel.addElement("VOICE")
			number = tel.addElement("NUMBER")
			number.addContent(utils.xmlify(usercol.workPhone))
			tel = vcard.addElement("TEL")
			tel.addElement("WORK")
			tel.addElement("FAX")
			number = tel.addElement("NUMBER")
			number.addContent(utils.xmlify(usercol.workFax))

			jabberid = vcard.addElement("JABBERID")
			jabberid.addContent(utils.xmlify(usercol.userinfo+"@"+config.jid))

			usercol.d.callback(vcard)
		elif usercol:
			usercol.d.callback(usercol.vcard)
		else:
			self.session.sendErrorMessage(self.session.jabberID, uin+"@"+config.jid, "cancel", "undefined-condition", "", "Unable to retrieve user information")
    def traverse_dom_for_cnxml(self, element):
        # traverse every element in tree, find matching environments, transform
        for child in element:
            self.traverse_dom_for_cnxml(child)

        childIndex = 0
        while childIndex < len(element):
            child = element[childIndex]

            if child.tag in ["video", "simulation", "presentation", "box"]:
                child.tag = "todo-" + child.tag
                childIndex += 1

            elif child.tag == "image":
                # <image> <arguments/> <src/> </image>
                mediaNode = utils.create_node("media")
                mediaNode.append(utils.create_node("image"))
                mediaNode.attrib["alt"] = "Image"
                urlNode = child.find("src")
                if urlNode is not None:
                    mediaNode[0].attrib["src"] = urlNode.text.strip()
                else:
                    mediaNode[0].attrib["src"] = ""
                mediaNode.tail = child.tail
                element[childIndex] = mediaNode
                childIndex += 1

            elif child.tag == "figure":
                typeNode = child.find("type")
                if typeNode is not None:
                    typ = typeNode.text.strip()
                    child.attrib["type"] = typ
                    typeNode.tag = "label"
                    typeNode.text = {"figure": "Figure", "table": "Table"}[typ]
                childIndex += 1

            elif child.tag == "caption":
                if (len(child) == 1) and (child[0].tag == "para"):
                    utils.etree_replace_with_node_list(child, child[0], child[0])
                childIndex += 1

            elif child.tag == "activity":
                # <activity type="activity"><title/> <section><title/>...</section> </activity>
                child.tag = "example"
                child.append(
                    utils.create_node(
                        "label",
                        text={
                            "g_experiment": "General experiment",
                            "f_experiment": "Formal experiment",
                            "i_experiment": "Informal experiment",
                            "activity": "Activity",
                            "Investigation": "Investigation",
                            "groupdiscussion": "Group discussion",
                            "casestudy": "Case study",
                            "project": "Project",
                        }[child.attrib["type"]],
                    )
                )
                pos = 1
                while pos < len(child):
                    if child[pos].tag == "section":
                        sectionNode = child[pos]
                        assert sectionNode[0].tag == "title"
                        del child[pos]
                        child.insert(pos, utils.create_node("para"))
                        child[pos].append(utils.create_node("emphasis", text=sectionNode[0].text.strip()))
                        child[pos][-1].attrib["effect"] = "bold"
                        pos += 1
                        sectionChildren = sectionNode.getchildren()
                        for i in range(1, len(sectionChildren)):
                            child.insert(pos, sectionChildren[i])
                            pos += 1
                    else:
                        pos += 1
                childIndex += 1

            elif child.tag == "worked_example":
                # <worked_example> <title/> <question/> <answer> ... <workstep> <title/> ... </workstep> </answer> </worked_example>
                child.tag = "example"
                newSubChildren = []
                newSubChildren.append(utils.create_node("label", text="Worked example"))
                pos = 1
                for subChild in child:
                    if subChild.tag == "title":
                        newSubChildren.append(subChild)
                    elif subChild.tag == "question":
                        newSubChildren.append(subChild)
                        subChild.tag = "section"
                        subChild.append(utils.create_node("title", text="Question"))
                    elif subChild.tag == "answer":
                        newSubChildren.append(subChild)
                        subChild.tag = "section"
                        subChild.append(utils.create_node("title", text="Answer"))
                        for x in subChild:
                            if x.tag == "workstep":
                                x.tag = "section"
                childIndex += 1

            elif child.tag == "note":
                child.insert(
                    0,
                    utils.create_node(
                        "label",
                        text={"warning": "Warning", "tip": "Tip", "note": "Note", "aside": "Interesting Fact"}.get(
                            child.attrib["type"], child.attrib["type"]
                        ),
                    ),
                )
                childIndex += 1

            elif child.tag == "math_identity":
                del element[childIndex]  # Remove math_identity from DOM, still available as child
                ruleNode = utils.create_node("rule")
                ruleNode.attrib["type"] = "Identity"
                child.tag = "statement"
                ruleNode.append(child)
                element.insert(childIndex, ruleNode)
                childIndex += 1

            elif child.tag == "nuclear_notation":
                namespace = "http://www.w3.org/1998/Math/MathML"
                mathNode = utils.create_node("math", namespace=namespace)
                mathNode.append(utils.create_node("msubsup", namespace=namespace))
                mathNode[-1].append(utils.create_node("mo", namespace=namespace, text=u"\u200b"))
                mathNode[-1].append(utils.create_node("mn", namespace=namespace, text=child.find("atomic_number").text))
                if child.find("mass_number") is not None:
                    massNumber = child.find("mass_number").text
                else:
                    massNumber = u"\u200b"
                mathNode[-1].append(utils.create_node("mn", namespace=namespace, text=massNumber))
                mathNode.append(utils.create_node("mtext", namespace=namespace, text=child.find("symbol").text))

                mathNode.tail = child.tail
                element[childIndex] = mathNode
                childIndex += 1

            elif child.tag == "math_extension":
                child.tag = "note"
                titleNode = child.find("title")
                if titleNode is not None:
                    titleNode.tag = "label"
                    titleNode.text = u"Extension \u2014 " + titleNode.text.strip()
                else:
                    child.insert(0, utils.create_node("label", text="Extension"))
                bodyNode = child.find("body")
                utils.etree_replace_with_node_list(child, bodyNode, bodyNode)
                childIndex += 1

            elif child.tag == "section":
                # Check that it is not an activity section
                if child.getparent().tag != "activity":
                    shortCodeNode = child.find("shortcode")
                    if shortCodeNode is None:
                        if (child.attrib.get("type") not in ["subsubsection", "subsubsubsection"]) and (
                            child.find("title").text.strip() != "Chapter summary"
                        ):
                            print 'WARNING: no shortcode for section "%s"' % child.find("title").text.strip()
                            shortcode = "SHORTCODE"
                        else:
                            shortcode = None
                    else:
                        if (child.attrib.get("type") in ["subsubsection", "subsubsubsection"]) or (
                            child.find("title").text.strip() == "Chapter summary"
                        ):
                            print 'WARNING: section "%s" should not have a shortcode' % child.find("title").text.strip()
                        shortcode = shortCodeNode.text.strip()
                        child.remove(shortCodeNode)
                    """ # Commented out so that shortcodes do not get displayed
                    if shortcode is not None:
                        titleNode = child.find('title')
                        if len(titleNode) == 0:
                            if titleNode.text is None:
                                titleNode.text = ''
                            titleNode.text += ' [' + shortcode + ']'
                        else:
                            if titleNode[-1].tail is None:
                                titleNode[-1].tail = ''
                            titleNode[-1].tail += ' [' + shortcode + ']'
                    """
                childIndex += 1

            elif child.tag == "latex":
                if child.attrib.get("display", "inline") == "block":
                    delimiters = "[]"
                else:
                    delimiters = "()"
                if child.text is None:
                    child.text = ""
                child.text = "\\" + delimiters[0] + child.text
                if len(child) > 0:
                    if child[-1].text is None:
                        child[-1].tail = ""
                    child[-1].tail += "\\" + delimiters[1]
                else:
                    child.text += "\\" + delimiters[1]
                utils.etree_replace_with_node_list(element, child, child)
                childIndex += len(child)

            elif child.tag in ["chem_compound", "spec_note"]:
                assert len(child) == 0, "<chem_compound> element not expected to have sub-elements."
                if child.text is None:
                    child.text = ""
                child.text = child.text.strip()
                assert child.text != "", "<chem_compound> element must contain text."

                compoundText = child.text
                pos = 0
                textOpen = False
                while pos < len(compoundText):
                    if "a" <= compoundText[pos].lower() <= "z":
                        if not textOpen:
                            compoundText = compoundText[:pos] + r"\text{" + compoundText[pos:]
                            textOpen = True
                            pos += len(r"\text{") + 1
                        else:
                            pos += 1
                    else:
                        if textOpen:
                            compoundText = compoundText[:pos] + "}" + compoundText[pos:]
                            textOpen = False
                            pos += 2
                        else:
                            pos += 1
                if textOpen:
                    compoundText += "}"
                compoundXml = utils.xmlify(r"\(" + compoundText + r"\)")

                compoundDom = etree.fromstring(compoundXml[compoundXml.find("<formula ") : compoundXml.rfind("\n</p>")])
                utils.etree_replace_with_node_list(element, child, compoundDom)
                childIndex += len(child)

            else:
                path = [child.tag]
                node = child
                while True:
                    node = node.getparent()
                    if node is None:
                        break
                    path.append(node.tag)
                path.reverse()

                namespaces = {"m": "http://www.w3.org/1998/Math/MathML"}
                valid = [
                    "emphasis",
                    "para",
                    "figure/type",
                    "exercise/problem",
                    "exercise/title",
                    "exercise/shortcodes/entry/number",
                    "exercise/shortcodes/entry/shortcode",
                    "exercise/shortcodes/entry/url",
                    "exercise/shortcodes/entry/todo-content",
                    "list/item/label",
                    "table/tgroup/tbody/row/entry",
                    "table/tgroup/colspec",
                    "definition/term",
                    "definition/meaning",
                    "sup",
                    "sub",
                    "m:mn",
                    "m:mo",
                    "m:mi",
                    "m:msup",
                    "m:mrow",
                    "m:math",
                    "m:mtable",
                    "m:mtr",
                    "m:mtd",
                    "m:msub",
                    "m:mfrac",
                    "m:msqrt",
                    "m:mspace",
                    "m:mstyle",
                    "m:mfenced",
                    "m:mtext",
                    "m:mroot",
                    "m:mref",
                    "m:msubsup",
                    "m:munderover",
                    "m:munder",
                    "m:mover",
                    "m:mphantom",
                    "equation",
                    "link",
                    "quote",
                    "rule/title",
                    "rule/statement",
                    "rule/proof",
                    "section/title",
                    "section/shortcode",
                    "image/arguments",
                    "image/src",
                    "number/coeff",
                    "number/exp",
                    "number/base",
                    "nuclear_notation/mass_number",
                    "nuclear_notation/atomic_number",
                    "nuclear_notation/symbol",
                    "pspicture/code",
                    "pspicture/usepackage",
                    "tikzpicture/code",
                    "video/title",
                    "video/shortcode",
                    "video/url",
                    "video/width",
                    "video/height",
                    "worked_example/answer/workstep/title",
                    "worked_example/question",
                    "worked_example/title",
                    "activity/title",
                    "math_extension/title",
                    "math_extension/body",
                    "math_identity",
                    "document/content/title",
                    "document/content/content",
                    "simulation/title",
                    "simulation/shortcode",
                    "simulation/url",
                    "simulation/width",
                    "simulation/height",
                    "simulation/embed",
                    "presentation/title",
                    "presentation/url",
                    "presentation/shortcode",
                    "presentation/embed",
                    "box",
                ]
                validSet = set([])
                for entry in valid:
                    entry = entry.split("/")
                    for i in range(len(entry)):
                        if ":" in entry[i]:
                            entry[i] = entry[i].split(":")
                            assert len(entry[i]) == 2
                            entry[i] = "{%s}%s" % (namespaces[entry[i][0]], entry[i][1])
                        validSet.add(tuple(entry[: i + 1]))
                valid = validSet

                passed = False
                for entry in valid:
                    if tuple(path[-len(entry) :]) == entry:
                        passed = True
                        break
                if not passed:
                    path = "/".join(path)
                    for key, url in namespaces.iteritems():
                        path = path.replace("{%s}" % url, key + ":")
                    LOGGER.info("Unhandled element: " + path)

                childIndex += 1
    def traverse_dom_for_cnxml(self, element):
        # traverse every element in tree, find matching environments, transform
        for child in element:
            self.traverse_dom_for_cnxml(child)

        childIndex = 0
        while childIndex < len(element):
            child = element[childIndex]

            if child.tag in ['video', 'simulation', 'presentation', 'box']:
                child.tag = 'todo-' + child.tag
                childIndex += 1

            elif child.tag == 'image':
                # <image> <arguments/> <src/> </image>
                mediaNode = utils.create_node('media')
                mediaNode.append(utils.create_node('image'))
                mediaNode.attrib['alt'] = 'Image'
                urlNode = child.find('src')
                if urlNode is not None:
                    mediaNode[0].attrib['src'] = urlNode.text.strip()
                else:
                    mediaNode[0].attrib['src'] = ''
                mediaNode.tail = child.tail
                element[childIndex] = mediaNode
                childIndex += 1

            elif child.tag == 'figure':
                typeNode = child.find('type')
                if typeNode is not None:
                    typ = typeNode.text.strip()
                    child.attrib['type'] = typ
                    typeNode.tag = 'label'
                    typeNode.text = {'figure': 'Figure', 'table': 'Table'}[typ]
                childIndex += 1

            elif child.tag == 'caption':
                if (len(child) == 1) and (child[0].tag == 'para'):
                    utils.etree_replace_with_node_list(child, child[0], child[0])
                childIndex += 1

            elif child.tag == 'activity':
                # <activity type="activity"><title/> <section><title/>...</section> </activity>
                child.tag = 'example'
                child.append(utils.create_node('label', text={
                    'g_experiment': 'General experiment',
                    'f_experiment': 'Formal experiment',
                    'i_experiment': 'Informal experiment',
                    'activity': 'Activity',
                    'Investigation': 'Investigation',
                    'groupdiscussion': 'Group discussion',
                    'casestudy': 'Case study',
                    'project': 'Project'}[child.attrib['type']]))
                pos = 1
                while pos < len(child):
                    if child[pos].tag == 'section':
                        sectionNode = child[pos]
                        assert sectionNode[0].tag == 'title'
                        del child[pos]
                        child.insert(pos, utils.create_node('para'))
                        child[pos].append(utils.create_node('emphasis', text=sectionNode[0].text.strip()))
                        child[pos][-1].attrib['effect'] = 'bold'
                        pos += 1
                        sectionChildren = sectionNode.getchildren()
                        for i in range(1, len(sectionChildren)):
                            child.insert(pos, sectionChildren[i])
                            pos += 1
                    else:
                        pos += 1
                childIndex += 1

            elif child.tag == 'worked_example':
                # <worked_example> <title/> <question/> <answer> ... <workstep> <title/> ... </workstep> </answer> </worked_example>
                child.tag = 'example'
                newSubChildren = []
                newSubChildren.append(utils.create_node('label', text="Worked example"))
                pos = 1
                for subChild in child:
                    if subChild.tag == 'title':
                        newSubChildren.append(subChild)
                    elif subChild.tag == 'question':
                        newSubChildren.append(subChild)
                        subChild.tag = 'section'
                        subChild.append(utils.create_node('title', text='Question'))
                    elif subChild.tag == 'answer':
                        newSubChildren.append(subChild)
                        subChild.tag = 'section'
                        subChild.append(utils.create_node('title', text='Answer'))
                        for x in subChild:
                            if x.tag == 'workstep':
                                x.tag = 'section'
                childIndex += 1

            elif child.tag == 'note':
                child.insert(0, utils.create_node('label', text={
                    'warning': 'Warning',
                    'tip': 'Tip',
                    'note': 'Note',
                    'aside': 'Interesting Fact'}.get(child.attrib['type'], child.attrib['type'])))
                childIndex += 1

            elif child.tag == 'math_identity':
                del element[childIndex] # Remove math_identity from DOM, still available as child
                ruleNode = utils.create_node('rule')
                ruleNode.attrib['type'] = 'Identity'
                child.tag = 'statement'
                ruleNode.append(child)
                element.insert(childIndex, ruleNode)
                childIndex += 1

            elif child.tag == 'nuclear_notation':
                namespace = 'http://www.w3.org/1998/Math/MathML'
                mathNode = utils.create_node('math', namespace=namespace)
                mathNode.append(utils.create_node('msubsup', namespace=namespace))
                mathNode[-1].append(utils.create_node('mo', namespace=namespace, text=u'\u200b'))
                mathNode[-1].append(utils.create_node('mn', namespace=namespace, text=child.find('atomic_number').text))
                if child.find('mass_number') is not None:
                    massNumber = child.find('mass_number').text
                else:
                    massNumber = u'\u200b'
                mathNode[-1].append(utils.create_node('mn', namespace=namespace, text=massNumber))
                mathNode.append(utils.create_node('mtext', namespace=namespace, text=child.find('symbol').text))

                mathNode.tail = child.tail
                element[childIndex] = mathNode
                childIndex += 1

            elif child.tag == 'math_extension':
                child.tag = 'note'
                titleNode = child.find('title')
                if titleNode is not None:
                    titleNode.tag = 'label'
                    titleNode.text = u'Extension \u2014 ' + titleNode.text.strip()
                else:
                    child.insert(0, utils.create_node('label', text='Extension'))
                bodyNode = child.find('body')
                utils.etree_replace_with_node_list(child, bodyNode, bodyNode)
                childIndex += 1

            elif child.tag == 'section':
                # Check that it is not an activity section
                if child.getparent().tag != 'activity':
                    shortCodeNode = child.find('shortcode')
                    if shortCodeNode is None:
                        if (child.attrib.get('type') not in ['subsubsection', 'subsubsubsection']) and (child.find('title').text.strip() != 'Chapter summary'):
                            print 'WARNING: no shortcode for section "%s"'%child.find('title').text.strip()
                            shortcode = 'SHORTCODE'
                        else:
                            shortcode = None
                    else:
                        if (child.attrib.get('type') in ['subsubsection', 'subsubsubsection']) or (child.find('title').text.strip() == 'Chapter summary'):
                            print 'WARNING: section "%s" should not have a shortcode'%child.find('title').text.strip()
                        shortcode = shortCodeNode.text.strip()
                        child.remove(shortCodeNode)
                    """ # Commented out so that shortcodes do not get displayed
                    if shortcode is not None:
                        titleNode = child.find('title')
                        if len(titleNode) == 0:
                            if titleNode.text is None:
                                titleNode.text = ''
                            titleNode.text += ' [' + shortcode + ']'
                        else:
                            if titleNode[-1].tail is None:
                                titleNode[-1].tail = ''
                            titleNode[-1].tail += ' [' + shortcode + ']'
                    """
                childIndex += 1

            elif child.tag == 'latex':
                if child.attrib.get('display', 'inline') == 'block':
                    delimiters = '[]'
                else:
                    delimiters = '()'
                if child.text is None:
                    child.text = ''
                child.text = '\\' + delimiters[0] + child.text
                if len(child) > 0:
                    if child[-1].text is None:
                        child[-1].tail = ''
                    child[-1].tail += '\\' + delimiters[1]
                else:
                    child.text += '\\' + delimiters[1]
                utils.etree_replace_with_node_list(element, child, child)
                childIndex += len(child)

            elif child.tag in ['chem_compound', 'spec_note']:
                assert len(child) == 0, "<chem_compound> element not expected to have sub-elements."
                if child.text is None:
                    child.text = ''
                child.text = child.text.strip()
                assert child.text != '', "<chem_compound> element must contain text."

                compoundText = child.text
                pos = 0
                textOpen = False
                while pos < len(compoundText):
                    if 'a' <= compoundText[pos].lower() <= 'z':
                        if not textOpen:
                            compoundText = compoundText[:pos] + r'\text{' + compoundText[pos:]
                            textOpen = True
                            pos += len(r'\text{') + 1
                        else:
                            pos += 1
                    else:
                        if textOpen:
                            compoundText = compoundText[:pos] + '}' + compoundText[pos:]
                            textOpen = False
                            pos += 2
                        else:
                            pos += 1
                if textOpen:
                    compoundText += '}'
                compoundXml = utils.xmlify(r'\(' + compoundText + r'\)')

                compoundDom = etree.fromstring(compoundXml[compoundXml.find('<formula '):compoundXml.rfind('\n</p>')])
                utils.etree_replace_with_node_list(element, child, compoundDom)
                childIndex += len(child)

            else:
                path = [child.tag]
                node = child
                while True:
                    node = node.getparent()
                    if node is None:
                        break
                    path.append(node.tag)
                path.reverse()

                namespaces = {'m': 'http://www.w3.org/1998/Math/MathML'}
                valid = [
                    'emphasis',
                    'para',
                    'figure/type',
                    'exercise/problem', 'exercise/title',
                    'exercise/shortcodes/entry/number', 'exercise/shortcodes/entry/shortcode', 'exercise/shortcodes/entry/url', 'exercise/shortcodes/entry/todo-content',
                    'list/item/label',
                    'table/tgroup/tbody/row/entry',
                    'table/tgroup/colspec',
                    'definition/term', 'definition/meaning',
                    'sup',
                    'sub',
                    'm:mn', 'm:mo', 'm:mi', 'm:msup', 'm:mrow', 'm:math', 'm:mtable', 'm:mtr', 'm:mtd', 'm:msub', 'm:mfrac', 'm:msqrt', 'm:mspace', 'm:mstyle', 'm:mfenced', 'm:mtext', 'm:mroot', 'm:mref', 'm:msubsup', 'm:munderover', 'm:munder', 'm:mover', 'm:mphantom',
                    'equation',
                    'link',
                    'quote',
                    'rule/title', 'rule/statement', 'rule/proof',

                    'section/title',
                    'section/shortcode',
                    'image/arguments',
                    'image/src',
                    'number/coeff', 'number/exp', 'number/base',
                    'nuclear_notation/mass_number', 'nuclear_notation/atomic_number', 'nuclear_notation/symbol',
                    'pspicture/code', 'pspicture/usepackage',
                    'tikzpicture/code',
                    'video/title', 'video/shortcode', 'video/url', 'video/width', 'video/height',
                    'worked_example/answer/workstep/title', 'worked_example/question', 'worked_example/title',
                    'activity/title',
                    'math_extension/title',
                    'math_extension/body',
                    'math_identity',
                    'document/content/title',
                    'document/content/content',
                    'simulation/title', 'simulation/shortcode', 'simulation/url', 'simulation/width', 'simulation/height', 'simulation/embed',
                    'presentation/title', 'presentation/url', 'presentation/shortcode', 'presentation/embed',
                    'box',
                ]
                validSet = set([])
                for entry in valid:
                    entry = entry.split('/')
                    for i in range(len(entry)):
                        if ':' in entry[i]:
                            entry[i] = entry[i].split(':')
                            assert len(entry[i]) == 2
                            entry[i] = '{%s}%s'%(namespaces[entry[i][0]], entry[i][1])
                        validSet.add(tuple(entry[:i+1]))
                valid = validSet

                passed = False
                for entry in valid:
                    if tuple(path[-len(entry):]) == entry:
                        passed = True
                        break
                if not passed:
                    path = '/'.join(path)
                    for key, url in namespaces.iteritems():
                        path = path.replace('{%s}'%url, key+':')
                    LOGGER.info('Unhandled element: ' + path)

                childIndex += 1