added ElementTree core components to xml.etree
diff --git a/Lib/xml/etree/ElementPath.py b/Lib/xml/etree/ElementPath.py
new file mode 100644
index 0000000..e8093c6
--- /dev/null
+++ b/Lib/xml/etree/ElementPath.py
@@ -0,0 +1,196 @@
+#

+# ElementTree

+# $Id: ElementPath.py 1858 2004-06-17 21:31:41Z Fredrik $

+#

+# limited xpath support for element trees

+#

+# history:

+# 2003-05-23 fl   created

+# 2003-05-28 fl   added support for // etc

+# 2003-08-27 fl   fixed parsing of periods in element names

+#

+# Copyright (c) 2003-2004 by Fredrik Lundh.  All rights reserved.

+#

+# fredrik@pythonware.com

+# http://www.pythonware.com

+#

+# --------------------------------------------------------------------

+# The ElementTree toolkit is

+#

+# Copyright (c) 1999-2004 by Fredrik Lundh

+#

+# By obtaining, using, and/or copying this software and/or its

+# associated documentation, you agree that you have read, understood,

+# and will comply with the following terms and conditions:

+#

+# Permission to use, copy, modify, and distribute this software and

+# its associated documentation for any purpose and without fee is

+# hereby granted, provided that the above copyright notice appears in

+# all copies, and that both that copyright notice and this permission

+# notice appear in supporting documentation, and that the name of

+# Secret Labs AB or the author not be used in advertising or publicity

+# pertaining to distribution of the software without specific, written

+# prior permission.

+#

+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD

+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-

+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR

+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY

+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,

+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS

+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE

+# OF THIS SOFTWARE.

+# --------------------------------------------------------------------

+

+##

+# Implementation module for XPath support.  There's usually no reason

+# to import this module directly; the <b>ElementTree</b> does this for

+# you, if needed.

+##

+

+import re

+

+xpath_tokenizer = re.compile(

+    "(::|\.\.|\(\)|[/.*:\[\]\(\)@=])|((?:\{[^}]+\})?[^/:\[\]\(\)@=\s]+)|\s+"

+    ).findall

+

+class xpath_descendant_or_self:

+    pass

+

+##

+# Wrapper for a compiled XPath.

+

+class Path:

+

+    ##

+    # Create an Path instance from an XPath expression.

+

+    def __init__(self, path):

+        tokens = xpath_tokenizer(path)

+        # the current version supports 'path/path'-style expressions only

+        self.path = []

+        self.tag = None

+        if tokens and tokens[0][0] == "/":

+            raise SyntaxError("cannot use absolute path on element")

+        while tokens:

+            op, tag = tokens.pop(0)

+            if tag or op == "*":

+                self.path.append(tag or op)

+            elif op == ".":

+                pass

+            elif op == "/":

+                self.path.append(xpath_descendant_or_self())

+                continue

+            else:

+                raise SyntaxError("unsupported path syntax (%s)" % op)

+            if tokens:

+                op, tag = tokens.pop(0)

+                if op != "/":

+                    raise SyntaxError(

+                        "expected path separator (%s)" % (op or tag)

+                        )

+        if self.path and isinstance(self.path[-1], xpath_descendant_or_self):

+            raise SyntaxError("path cannot end with //")

+        if len(self.path) == 1 and isinstance(self.path[0], type("")):

+            self.tag = self.path[0]

+

+    ##

+    # Find first matching object.

+

+    def find(self, element):

+        tag = self.tag

+        if tag is None:

+            nodeset = self.findall(element)

+            if not nodeset:

+                return None

+            return nodeset[0]

+        for elem in element:

+            if elem.tag == tag:

+                return elem

+        return None

+

+    ##

+    # Find text for first matching object.

+

+    def findtext(self, element, default=None):

+        tag = self.tag

+        if tag is None:

+            nodeset = self.findall(element)

+            if not nodeset:

+                return default

+            return nodeset[0].text or ""

+        for elem in element:

+            if elem.tag == tag:

+                return elem.text or ""

+        return default

+

+    ##

+    # Find all matching objects.

+

+    def findall(self, element):

+        nodeset = [element]

+        index = 0

+        while 1:

+            try:

+                path = self.path[index]

+                index = index + 1

+            except IndexError:

+                return nodeset

+            set = []

+            if isinstance(path, xpath_descendant_or_self):

+                try:

+                    tag = self.path[index]

+                    if not isinstance(tag, type("")):

+                        tag = None

+                    else:

+                        index = index + 1

+                except IndexError:

+                    tag = None # invalid path

+                for node in nodeset:

+                    new = list(node.getiterator(tag))

+                    if new and new[0] is node:

+                        set.extend(new[1:])

+                    else:

+                        set.extend(new)

+            else:

+                for node in nodeset:

+                    for node in node:

+                        if path == "*" or node.tag == path:

+                            set.append(node)

+            if not set:

+                return []

+            nodeset = set

+

+_cache = {}

+

+##

+# (Internal) Compile path.

+

+def _compile(path):

+    p = _cache.get(path)

+    if p is not None:

+        return p

+    p = Path(path)

+    if len(_cache) >= 100:

+        _cache.clear()

+    _cache[path] = p

+    return p

+

+##

+# Find first matching object.

+

+def find(element, path):

+    return _compile(path).find(element)

+

+##

+# Find text for first matching object.

+

+def findtext(element, path, default=None):

+    return _compile(path).findtext(element, default)

+

+##

+# Find all matching objects.

+

+def findall(element, path):

+    return _compile(path).findall(element)

+