183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# ElementTree 383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# $Id: ElementInclude.py 3375 2008-02-13 08:05:08Z fredrik $ 483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# limited xinclude support for element trees 683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# history: 883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 2003-08-15 fl created 983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 2003-11-14 fl fixed default loader 1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Copyright (c) 2003-2004 by Fredrik Lundh. All rights reserved. 1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# fredrik@pythonware.com 1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# http://www.pythonware.com 1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# -------------------------------------------------------------------- 1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# The ElementTree toolkit is 1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Copyright (c) 1999-2008 by Fredrik Lundh 2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# By obtaining, using, and/or copying this software and/or its 2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# associated documentation, you agree that you have read, understood, 2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# and will comply with the following terms and conditions: 2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Permission to use, copy, modify, and distribute this software and 2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# its associated documentation for any purpose and without fee is 2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# hereby granted, provided that the above copyright notice appears in 2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# all copies, and that both that copyright notice and this permission 2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# notice appear in supporting documentation, and that the name of 3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Secret Labs AB or the author not be used in advertising or publicity 3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# pertaining to distribution of the software without specific, written 3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# prior permission. 3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD 3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- 3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR 3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# OF THIS SOFTWARE. 4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# -------------------------------------------------------------------- 4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Licensed to PSF under a Contributor Agreement. 4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# See http://www.python.org/psf/license for licensing details. 4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## 4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Limited XInclude support for the ElementTree package. 4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## 5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport copy 5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom . import ElementTree 5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehXINCLUDE = "{http://www.w3.org/2001/XInclude}" 5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehXINCLUDE_INCLUDE = XINCLUDE + "include" 5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehXINCLUDE_FALLBACK = XINCLUDE + "fallback" 5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## 6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Fatal include error. 6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass FatalIncludeError(SyntaxError): 6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## 6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Default loader. This loader reads an included resource from disk. 6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @param href Resource reference. 6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @param parse Parse mode. Either "xml" or "text". 7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @param encoding Optional text encoding. 7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @return The expanded resource. If the parse mode is "xml", this 7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# is an ElementTree instance. If the parse mode is "text", this 7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# is a Unicode string. If the loader fails, it can return None 7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# or raise an IOError exception. 7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @throws IOError If the loader fails to load the resource. 7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef default_loader(href, parse, encoding=None): 7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh file = open(href) 7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if parse == "xml": 8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = ElementTree.parse(file).getroot() 8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = file.read() 8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if encoding: 8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = data.decode(encoding) 8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh file.close() 8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return data 8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## 8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Expand XInclude directives. 9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# 9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @param elem Root element. 9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @param loader Optional resource loader. If omitted, it defaults 9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# to {@link default_loader}. If given, it should be a callable 9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# that implements the same interface as <b>default_loader</b>. 9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @throws FatalIncludeError If the function fails to include a given 9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# resource, or if the tree contains malformed XInclude elements. 9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# @throws IOError If the function fails to load a given resource. 9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef include(elem, loader=None): 10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if loader is None: 10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh loader = default_loader 10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # look for xinclude elements 10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh i = 0 10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh while i < len(elem): 10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh e = elem[i] 10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if e.tag == XINCLUDE_INCLUDE: 10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # process xinclude directive 10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh href = e.get("href") 10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh parse = e.get("parse", "xml") 11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if parse == "xml": 11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh node = loader(href, parse) 11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if node is None: 11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise FatalIncludeError( 11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "cannot load %r as %r" % (href, parse) 11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh node = copy.copy(node) 11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if e.tail: 11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh node.tail = (node.tail or "") + e.tail 11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elem[i] = node 12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif parse == "text": 12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text = loader(href, parse, e.get("encoding")) 12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if text is None: 12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise FatalIncludeError( 12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "cannot load %r as %r" % (href, parse) 12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if i: 12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh node = elem[i-1] 12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh node.tail = (node.tail or "") + text + (e.tail or "") 12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elem.text = (elem.text or "") + text + (e.tail or "") 13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh del elem[i] 13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh continue 13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise FatalIncludeError( 13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "unknown parse type in xi:include tag (%r)" % parse 13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif e.tag == XINCLUDE_FALLBACK: 13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise FatalIncludeError( 13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh "xi:fallback tag must be child of xi:include (%r)" % e.tag 14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ) 14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh include(e, loader) 14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh i = i + 1 144