xmlutils.py
Go to the documentation of this file.
00001 # Copyright (c) 2015, Open Source Robotics Foundation, Inc.
00002 # Copyright (c) 2013, Willow Garage, Inc.
00003 # All rights reserved.
00004 #
00005 # Redistribution and use in source and binary forms, with or without
00006 # modification, are permitted provided that the following conditions are met:
00007 #
00008 #     * Redistributions of source code must retain the above copyright
00009 #       notice, this list of conditions and the following disclaimer.
00010 #     * Redistributions in binary form must reproduce the above copyright
00011 #       notice, this list of conditions and the following disclaimer in the
00012 #       documentation and/or other materials provided with the distribution.
00013 #     * Neither the name of the Open Source Robotics Foundation, Inc.
00014 #       nor the names of its contributors may be used to endorse or promote
00015 #       products derived from this software without specific prior
00016 #       written permission.
00017 #
00018 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 # POSSIBILITY OF SUCH DAMAGE.
00029 
00030 # Authors: Stuart Glaser, William Woodall, Robert Haschke
00031 # Maintainer: Morgan Quigley <morgan@osrfoundation.org>
00032 
00033 import xml
00034 from .color import warning
00035 
00036 def first_child_element(elt):
00037     c = elt.firstChild
00038     while c and c.nodeType != xml.dom.Node.ELEMENT_NODE:
00039         c = c.nextSibling
00040     return c
00041 
00042 
00043 def next_sibling_element(node):
00044     c = node.nextSibling
00045     while c and c.nodeType != xml.dom.Node.ELEMENT_NODE:
00046         c = c.nextSibling
00047     return c
00048 
00049 
00050 def replace_node(node, by, content_only=False):
00051     parent = node.parentNode
00052 
00053     if by is not None:
00054         if not isinstance(by, list):
00055             by = [by]
00056 
00057         # insert new content before node
00058         for doc in by:
00059             if content_only:
00060                 c = doc.firstChild
00061                 while c:
00062                     n = c.nextSibling
00063                     parent.insertBefore(c, node)
00064                     c = n
00065             else:
00066                 parent.insertBefore(doc, node)
00067 
00068     # remove node
00069     parent.removeChild(node)
00070 
00071 
00072 def attribute(tag, a):
00073     """
00074     Helper function to fetch a single attribute value from tag
00075     :param tag (xml.dom.Element): DOM element node
00076     :param a (str): attribute name
00077     :return: attribute value if present, otherwise None
00078     """
00079     if tag.hasAttribute(a):
00080         # getAttribute returns empty string for non-existent attributes,
00081         # which makes it impossible to distinguish with empty values
00082         return tag.getAttribute(a)
00083     else:
00084         return None
00085 
00086 
00087 def opt_attrs(tag, attrs):
00088     """
00089     Helper routine for fetching optional tag attributes
00090     :param tag (xml.dom.Element): DOM element node
00091     :param attrs [str]: list of attributes to fetch
00092     """
00093     return [attribute(tag, a) for a in attrs]
00094 
00095 
00096 def reqd_attrs(tag, attrs):
00097     """
00098     Helper routine for fetching required tag attributes
00099     :param tag (xml.dom.Element): DOM element node
00100     :param attrs [str]: list of attributes to fetch
00101     :raise RuntimeError: if required attribute is missing
00102     """
00103     result = opt_attrs(tag, attrs)
00104     for (res, name) in zip(result, attrs):
00105         if res is None:
00106             raise RuntimeError("%s: missing attribute '%s'" % (tag.nodeName, name))
00107     return result
00108 
00109 
00110 def check_attrs(tag, required, optional):
00111     """
00112     Helper routine to fetch required and optional attributes
00113     and complain about any additional attributes.
00114     :param tag (xml.dom.Element): DOM element node
00115     :param required [str]: list of required attributes
00116     :param optional [str]: list of optional attributes
00117     """
00118     result = reqd_attrs(tag, required)
00119     result.extend(opt_attrs(tag, optional))
00120     allowed = required + optional
00121     extra = [a for a in tag.attributes.keys() if a not in allowed]
00122     if extra:
00123         warning("%s: unknown attribute(s): %s" % (tag.nodeName, ', '.join(extra)))
00124     return result
00125 
00126 
00127 # Better pretty printing of xml
00128 # Taken from http://ronrothman.com/public/leftbraned/xml-dom-minidom-toprettyxml-and-silly-whitespace/
00129 def fixed_writexml(self, writer, indent="", addindent="", newl=""):
00130     # indent = current indentation
00131     # addindent = indentation to add to higher levels
00132     # newl = newline string
00133     writer.write(indent + "<" + self.tagName)
00134 
00135     attrs = self._get_attributes()
00136     a_names = list(attrs.keys())
00137     a_names.sort()
00138 
00139     for a_name in a_names:
00140         writer.write(" %s=\"" % a_name)
00141         xml.dom.minidom._write_data(writer, attrs[a_name].value)
00142         writer.write("\"")
00143     if self.childNodes:
00144         if len(self.childNodes) == 1 \
00145            and self.childNodes[0].nodeType == xml.dom.minidom.Node.TEXT_NODE:
00146             writer.write(">")
00147             self.childNodes[0].writexml(writer, "", "", "")
00148             writer.write("</%s>%s" % (self.tagName, newl))
00149             return
00150         writer.write(">%s" % newl)
00151         for node in self.childNodes:
00152             # skip whitespace-only text nodes
00153             if node.nodeType == xml.dom.minidom.Node.TEXT_NODE and \
00154                     (not node.data or node.data.isspace()):
00155                 continue
00156             node.writexml(writer, indent + addindent, addindent, newl)
00157         writer.write("%s</%s>%s" % (indent, self.tagName, newl))
00158     else:
00159         writer.write("/>%s" % newl)
00160 # replace minidom's function with ours
00161 xml.dom.minidom.Element.writexml = fixed_writexml
00162 
00163 


xacro
Author(s): Stuart Glaser, William Woodall
autogenerated on Sat Jun 8 2019 18:50:42