Source code for nxswriter.FetchNameHandler

#!/usr/bin/env python
#   This file is part of nexdatas - Tango Server for NeXus data writer
#
#    Copyright (C) 2012-2017 DESY, Jan Kotanski <jkotan@mail.desy.de>
#
#    nexdatas is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    nexdatas is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with nexdatas.  If not, see <http://www.gnu.org/licenses/>.
#

""" SAX parser for fetching name attributes of tags """

from xml import sax

import sys
import os
import weakref


from .Errors import XMLSyntaxError


[docs]class TNObject(object): """ Type Name object """ def __init__(self, name="root", nxtype=None, parent=None): """ constructor :brief: It sets default values of TNObject :param name: name of the object :type name: :obj:`str` :param nxtype: Nexus type of the object :type nxtype: :obj:`str` :param parent: object parent :type parent: :class:`nxswriter.Element.Element` """ #: (:obj:`str`) object name self.name = name #: (:obj:`str`) object Nexus type self.nxtype = nxtype #: (:class:`nxswriter.Element.Element`) object parent self.parent = weakref.ref(parent) if parent else lambda: None #: (:obj`:list` <:class:`nxswriter.Element.Element`>) object children self.children = [] if hasattr(self.parent(), "children"): self.parent().children.append(self)
[docs] def child(self, name='', nxtype=''): """ get child by name or nxtype :param name: group name :type name: :obj:`str` :param nxtype: nexus group type :type nxtype: :obj:`str` :returns: child instance :rtype: :class:`nxswriter.Element.Element` """ if name: found = None for ch in self.children: if ch.name == name.strip(): found = ch break return found elif nxtype: found = None for ch in self.children: if ch.nxtype == nxtype: found = ch break return found else: if len(self.children) > 0: return self.children[0]
[docs]class FetchNameHandler(sax.ContentHandler): """ SAX2 parser """ def __init__(self, streams=None): """ constructor :brief: It constructs parser handler for fetching group names :param streams: tango-like steamset class :type streams: :class:`StreamSet` or :class:`tango.LatestDeviceImpl` """ sax.ContentHandler.__init__(self) #: (:class:`TNObject`) tree of TNObjects with names and types self.groupTypes = TNObject() #: (:class:`TNObject`) current object self.__current = self.groupTypes #: (:obj:`list` <:obj:`str`>) stack with open tag names self.__stack = [] #: (:obj:`str`) name of attribute tag self.__attrName = "" #: (:obj:`list` <:obj:`str`>) content of attribute tag self.__content = [] #: (:obj:`bool`) True if inside attribute tag self.__attribute = False #: (:class:`StreamSet` or :class:`tango.LatestDeviceImpl`) stream set self._streams = streams
[docs] def startElement(self, name, attrs): """ parses the opening tag :param name: tag name :type name: :obj:`str` :param attrs: attribute dictionary :type attrs: :obj:`dict` <:obj:`str`, :obj:`str`> """ ttype = "" tname = "" if name == "group": if "type" in attrs.keys(): ttype = attrs["type"] if "name" in attrs.keys(): tname = attrs["name"] self.__current = TNObject(tname.strip(), ttype.strip(), self.__current) self.__stack.append(name) elif name == "attribute" and self.__stack[-1] == "group": self.__content = [] self.__attribute = True if "name" in attrs.keys() and attrs["name"] in ["name", "type"]: self.__attrName = attrs["name"]
[docs] def characters(self, content): """ adds the tag content :param content: partial content of the tag :type content: :obj:`str` """ if self.__attribute and self.__stack[-1] == "group": self.__content.append(content)
[docs] def endElement(self, name): """ parses an closing tag :param name: tag name :type name: :obj:`str` """ if name == "group": if not self.__current.nxtype or not self.__current.name: if self.__current.nxtype and len(self.__current.nxtype) > 2: self.__current.name = self.__current.nxtype[2:] else: if self._streams: self._streams.error( "FetchNameHandler::endElement() - " "The group type not defined", std=False) raise XMLSyntaxError("The group type not defined") self.__current = self.__current.parent() self.__stack.pop() if name == "attribute" and self.__stack[-1] == "group": if self.__attrName: content = ("".join(self.__content)).strip() if content: if self.__attrName == "name": self.__current.name = content.strip() if self.__attrName == "type": self.__current.nxtype = content.strip() self.__attribute = False self.__content = [] self.__attrName = None
if __name__ == "__main__": if len(sys.argv) < 2: print("usage: FetchNameHadler.py <XMLinput>") else: #: (:obj:`str`) input XML file fi = sys.argv[1] if os.path.exists(fi): #: (:class:`xml.sax.xmlreader.XMLReader`) parser object parser = sax.make_parser() #: (:class:`FetchNameHandler`) SAX2 handler object handler = FetchNameHandler() parser.setContentHandler(handler) with open(fi) as fl: parser.parse(fl) print("GT: %s" % handler.groupTypes)