def setUp( self ): self.segments1= [ ['ST', '278', '242835'] ] self.segments2= [ ['ST', '279', '242835'] ] self.parserQual= Segment( "ST", Properties( qual=(1,"278"), desc="ST", req_sit="R" ), Element( "ST01", Properties(position=1,codes=["278"]) ), ) self.parserNonQual= Segment( "ST", Properties( desc="ST", req_sit="R" ) )
def testBadLoop(self): """Can't include a Message within a Loop.""" self.assertRaises( StructureError, Loop, "name", Properties( desc="desc", req_sit="R", repeat="1"), Message("bad", Properties(desc="bad")))
def build(self, xmlDoc, name=None): """Build the overall :class:`X12.parse.Message` parser. :param xmlDoc: a :class:`XMLParser` which has parsed the data, codes and message structure documents. :param name: Optional name of the Message to build; this will use the xid attribute provided in the XML if no overriding name is provided here. :returns: :class:`X12.parse.Message` parser. """ self.dataElements(xmlDoc) self.codes(xmlDoc) doc = xmlDoc.doc.documentElement assert doc.nodeType == DOM.Node.ELEMENT_NODE and doc.nodeName == "transaction" xid = doc.getAttribute('xid') desc = self.getChildTextValue(doc, "name") if name is None: name = xid self.log.info("Message %s: xid=%s desc=%s", name, xid, desc) self.top = Message(name, Properties(desc=desc)) for c in doc.childNodes: # Want to preserve the original XML order of <loop> and <segment> if c.nodeType != DOM.Node.ELEMENT_NODE: continue if c.nodeName == "loop": self.buildLoop(c, self.top) elif c.nodeName in ("name", ): pass # Already consumed this else: warnings.warn(XMLWarning("Unexpected %r" % (c, ))) self.log.warning("*** Unexpected %r", c) return self.top
def buildSegment(name, desc, fieldText): """Convert a block of text to a Segment definition. The block of text has one Element defined on each line. The Element definition is an Element name, one or more spaces, and the element description. :param name: the name of the segment :param desc: the description of the segment :param fieldText: a block of text, with one Element name and description per line. :returns: :class:`X12.parse.Segment` definition """ segment = Segment(name, Properties(desc=desc)) for line in filter(None, fieldText.splitlines()): name, description = line.strip().split(None, 1) element = Element(name, Properties(desc=description, codes=[])) segment.append(element) return segment
def buildSegment(name, desc, fieldText): """Convert a block of text to a Segment definition. The block of text has one Element defined on each line. The Element definition is an Element name, one or more spaces, and the element description. :param name: the name of the segment :param desc: the description of the segment :param fieldText: a block of text, with one Element name and description per line. :returns: :class:`X12.parse.Segment` definition """ theSeg = Segment(name, Properties(desc=desc)) for line in fieldText.splitlines(): clean = line.strip() eltName, space, eltDesc = clean.partition(" ") theElt = Element(eltName, Properties(desc=eltDesc)) theSeg.append(theElt) return theSeg
def buildComposite(self, compositeNode, context, nesting=0): """Build a Composite from a list of sub-Elements. Note that the ISA segment provides the Component Element Separator in ISA16. Composites are tricky. We have two choices. 1. Treat them as just a sequence of Elements -- which they are for RDBMS purposes. However, this makes compliance checking hard, since we have to look inside the composite. We have to turn off "match" for each Element of the Composite, otherwise, we won't be able to look into the segment data properly. 2. Treat them as a subclass of Elements -- which is a lot of fooling around to support a few compliance checks. We have to provide a composite match function and we have to make use of punctuation in the ISA segment for sub-parsing each Composite when we finally figure out what the Segment and Elements. :param compositeNode: a :mod:`xml.dom` Element with a name of :samp:`composite` :param context: The Segment which contains this Composite :param nesting: The current nesting level used to indent the log messages. """ assert compositeNode.nodeType == DOM.Node.ELEMENT_NODE and compositeNode.nodeName == "composite" name = self.getChildTextValue(compositeNode, "name") usage = self.getChildTextValue(compositeNode, "usage") seq = self.getChildTextValue(compositeNode, "seq") data_ele = self.getChildTextValue(compositeNode, "data_ele") refdes = self.getChildTextValue(compositeNode, "refdes") repeat = self.getChildTextValue(compositeNode, "repeat") # TODO add support self.log.debug( "%*sComposite name %r usage %r seq %r data_ele %r refdes %r", nesting * 2, '', name, usage, seq, data_ele, refdes) theComposite = Composite( data_ele, Properties(desc=name, req_sit=usage, seq=seq, refdes=refdes, repeat=repeat)) for c in compositeNode.childNodes: # Want to preserve the original XML order of <element> if c.nodeType != DOM.Node.ELEMENT_NODE: continue if c.nodeName == "element": self.buildElement(c, theComposite, nesting + 1) elif c.nodeName in ("name", "usage", "seq", "data_ele", 'refdes', 'repeat'): pass # already consumed else: warnings.warn(XMLWarning("Unexpected %r" % (c, ))) self.log.warning("*** Unexpected %r", c) context.append(theComposite)
def buildLoop(self, loopNode, context, nesting=0): """Loop contains Segments and Loops. Empty Loops create a warning, and are dropped. :param loopNode: a :mod:`xml.dom` Element with a name of :samp:`loop` :param context: The Loop which contains this Loop or Segment. :param nesting: The current nesting level used to indent the log messages. """ assert loopNode.nodeType == DOM.Node.ELEMENT_NODE and loopNode.nodeName == "loop" loopXid = loopNode.getAttribute('xid') loopType = loopNode.getAttribute('type') name = self.getChildTextValue(loopNode, "name") usage = self.getChildTextValue(loopNode, "usage") pos = self.getChildTextValue(loopNode, "pos") repeat = self.getChildTextValue(loopNode, "repeat") self.log.debug( "%*sLoop xid %r type %r: name %r usage %r pos %r repeat %r", nesting * 2, '', loopXid, loopType, name, usage, pos, repeat) theLoop = Loop( loopXid, Properties(desc=name, req_sit=usage, position=pos, repeat=repeat, looptype=loopType), ) for c in loopNode.childNodes: # Want to preserve the original XML order of <loop> and <segment> if c.nodeType != DOM.Node.ELEMENT_NODE: continue if c.nodeName == "loop": self.buildLoop(c, theLoop, nesting + 1) elif c.nodeName == "segment": self.buildSegment(c, theLoop, nesting + 1) elif c.nodeName in ( "name", "usage", "pos", "repeat", ): pass # already consumed else: warnings.warn(XMLWarning("Unexpected %r" % (c, ))) self.log.warning("*** Unexpected %r", c) if len(theLoop.structure) == 0: warnings.warn(EmptyLoopWarning("Empty Loop %r" % (theLoop, ))) # optimize this out of existence else: context.append(theLoop)
def buildSegment(self, segmentNode, context, nesting=0): """Segment contains Elements and Composites. :param segmentNode: a :mod:`xml.dom` Element with a name of :samp:`segment` :param context: The Loop which contains this Segment. :param nesting: The current nesting level used to indent the log messages. """ assert segmentNode.nodeType == DOM.Node.ELEMENT_NODE and segmentNode.nodeName == "segment" segXid = segmentNode.getAttribute('xid') name = self.getChildTextValue(segmentNode, "name") usage = self.getChildTextValue(segmentNode, "usage") pos = self.getChildTextValue(segmentNode, "pos") max_use = self.getChildTextValue(segmentNode, "max_use") syntax = self.getChildTextValue(segmentNode, "syntax") self.log.debug( "%*sSegment xid %r: name %r usage %r pos %r max_use %r syntax %r", nesting * 2, '', segXid, name, usage, pos, max_use, syntax) theSegment = Segment( segXid, Properties(desc=name, req_sit=usage, position=pos, repeat=max_use, syntax=syntax), ) for c in segmentNode.childNodes: # Want to preserve the original XML order of <element> and <composite> if c.nodeType != DOM.Node.ELEMENT_NODE: continue if c.nodeName == "element": self.buildElement(c, theSegment, nesting + 1) elif c.nodeName == "composite": self.buildComposite(c, theSegment, nesting + 1) elif c.nodeName in ( "name", "usage", "pos", "max_use", "syntax", ): pass # already consumed else: warnings.warn(XMLWarning("Unexpected %r" % (c, ))) self.log.warning("*** Unexpected %r", c) context.append(theSegment)
# # Generated by TigerShark.tools.convertPyX12 on 2012-10-03 14:38:27.454816 # from tigershark.X12.parse import Message, Loop, Segment, Composite, Element, Properties parsed_270_HEADER = Loop( u'HEADER', Properties(looptype=u'wrapper',repeat=u'1',pos=u'015',req_sit=u'R',desc=u'Table 1 - Header'), Segment( u'BHT', Properties(syntax='',req_sit=u'R',repeat=u'1',pos=u'020',desc=u'Beginning of Hierarchical Transaction'), Element( u'BHT01', Properties(desc=u'Hierarchical Structure Code', req_sit=u'R', data_type=(u'ID',u'4',u'4'), position=1, codes=[u'0022'] ) ), Element( u'BHT02', Properties(desc=u'Transaction Set Purpose Code', req_sit=u'R', data_type=(u'ID',u'2',u'2'), position=2, codes=[u'01', u'13', u'36'] ) ), Element( u'BHT03', Properties(desc=u'Reference Identification', req_sit=u'S', data_type=(u'AN',u'1',u'50'), position=3, codes=[] ) ), Element( u'BHT04', Properties(desc=u'Date', req_sit=u'R', data_type=(u'DT',u'8',u'8'), position=4, codes=[] ) ), Element( u'BHT05', Properties(desc=u'Time', req_sit=u'R', data_type=(u'TM',u'4',u'8'), position=5, codes=[] ) ), Element( u'BHT06', Properties(desc=u'Transaction Type Code', req_sit=u'S', data_type=(u'ID',u'2',u'2'), position=6, codes=[u'RT', u'RU'] ) ), ), ) parsed_270_2100A = Loop( u'2100A', Properties(looptype='',repeat=u'1',pos=u'030',req_sit=u'R',desc=u'Information Source Name'), Segment( u'NM1', Properties(syntax='',req_sit=u'R',repeat=u'1',pos=u'030',desc=u'Information Source Name'), Element( u'NM101', Properties(desc=u'Entity Identifier Code', req_sit=u'R', data_type=(u'ID',u'2',u'3'), position=1, codes=[u'2B', u'36', u'GP', u'P5', u'PR'] ) ), Element( u'NM102', Properties(desc=u'Entity Type Qualifier', req_sit=u'R', data_type=(u'ID',u'1',u'1'), position=2, codes=[u'1', u'2'] ) ), Element( u'NM103', Properties(desc=u'Name Last or Organization Name', req_sit=u'S', data_type=(u'AN',u'1',u'60'), position=3, codes=[] ) ), Element( u'NM104', Properties(desc=u'Name First', req_sit=u'S', data_type=(u'AN',u'1',u'35'), position=4, codes=[] ) ), Element( u'NM105', Properties(desc=u'Name Middle', req_sit=u'S', data_type=(u'AN',u'1',u'25'), position=5,
def buildElement(self, elementNode, context, nesting=0): """Element is the fundamental piece of data in a Segment or Composite. Elements can have code definitions or can reference external code definitions. .. todo:: XXX - Use external code definitions. :param elementNode: a :mod:`xml.dom` Element with a name of :samp:`element` :param context: The Segment or Composite which contains this Element :param nesting: The current nesting level used to indent the log messages. """ assert elementNode.nodeType == DOM.Node.ELEMENT_NODE and elementNode.nodeName == "element" eltXid = elementNode.getAttribute('xid') name = self.getChildTextValue(elementNode, "name") usage = self.getChildTextValue(elementNode, "usage") seq = self.getChildTextValue(elementNode, "seq") data_ele = self.getChildTextValue(elementNode, "data_ele") repeat = self.getChildTextValue(elementNode, "repeat") # TODO add support self.log.debug("%*sElement id %r name %r usage %r seq %r data_ele %r", nesting * 2, '', eltXid, name, usage, seq, data_ele) if not self.dataDictionary.has_key(data_ele): warnings.warn( UnknownElementWarning("No Data Element %r %r %r" % ( eltXid, data_ele, name, ))) data_type_tuple = (None, None, None) else: name, data_type_tuple = self.dataDictionary[data_ele] codes = [] for c in elementNode.childNodes: if c.nodeType != DOM.Node.ELEMENT_NODE: continue if c.nodeName == "valid_codes": if c.getAttribute("external") != "": pass # reference to codes.xml codes # XXX - Handle external code list warnings.warn(Extension("External Codes Not Implemented")) else: codes = self.getValidCodes(c) elif c.nodeName in ("name", "usage", "seq", "data_ele", 'repeat'): pass # already consumed else: warnings.warn(XMLWarning("Unexpected %r" % (c, ))) self.log.warning("*** Unexpected %r", c) theElement = Element( eltXid, Properties( desc=name, req_sit=usage, seq=seq, data_ele=data_ele, data_type=data_type_tuple, codes=codes, repeat=repeat, )) if self.dataDictionary.has_key(data_ele) and len(codes) != 0: #self.log2.debug( "Segment Qual Parameter? %r %r", self.dataDictionary[data_ele], codes ) pass context.append(theElement)
#!/usr/bin/env python # EXAMPLE IMPLEMENTATION - 278 Request Parser from tigershark.X12.parse import Message from tigershark.X12.parse import Loop from tigershark.X12.parse import Segment from tigershark.X12.parse import Composite from tigershark.X12.parse import Element from tigershark.X12.parse import Properties loop2000A = Loop( "2000A", Properties( desc="2000A", req_sit="R", repeat="1", ), Segment( "HL", Properties(qual=(3, "20"), desc="Utilization Management Organization (UMO) Level", req_sit="R", repeat="1"), Element("HL03", Properties(position=3, codes=["20"]))), Loop( "2010A", Properties( desc="2010A", req_sit="R", repeat=">1", ), Segment(
for parser in get_parsers(self.transaction_set_id, self.version_tuple): try: return parser.unmarshall(x12_contents, **kwargs) except ParseError: continue else: # Let the last parser raise. return parser.unmarshall(x12_contents, **kwargs) STLoop = Loop( u'ST_LOOP', Properties( position=u'0200', looptype=u'explicit', repeat=u'>1', req_sit=u'R', desc=u'Transaction Set Header', ), standardSegment.st, ) GSLoop = Loop( u'GS_LOOP', Properties( position=u'0200', looptype=u'explicit', repeat=u'>1', req_sit=u'R', desc=u'Functional Group Header', ),
# # Generated by TigerShark.tools.convertPyX12 on 2012-07-10 16:29:58.460993 # from tigershark.X12.parse import Message, Loop, Segment, Composite, Element, Properties parsed_277_HEADER = Loop( u'HEADER', Properties(looptype=u'wrapper',repeat=u'1',pos=u'015',req_sit=u'R',desc=u'Table 1 - Header'), Segment( u'BHT', Properties(syntax='',req_sit=u'R',repeat=u'1',pos=u'020',desc=u'Beginning of Hierarchical Transaction'), Element( u'BHT01', Properties(desc=u'Hierarchical Structure Code', req_sit=u'R', data_type=(u'ID',u'4',u'4'), position=1, codes=[u'0010'] ) ), Element( u'BHT02', Properties(desc=u'Transaction Set Purpose Code', req_sit=u'R', data_type=(u'ID',u'2',u'2'), position=2, codes=[u'08'] ) ), Element( u'BHT03', Properties(desc=u'Reference Identification', req_sit=u'R', data_type=(u'AN',u'1',u'50'), position=3, codes=[] ) ), Element( u'BHT04', Properties(desc=u'Date', req_sit=u'R', data_type=(u'DT',u'8',u'8'), position=4, codes=[] ) ), Element( u'BHT05', Properties(desc=u'Time', req_sit=u'N', data_type=(u'TM',u'4',u'8'), position=5, codes=[] ) ), Element( u'BHT06', Properties(desc=u'Transaction Type Code', req_sit=u'R', data_type=(u'ID',u'2',u'2'), position=6, codes=[u'DG'] ) ), ), ) parsed_277_2100A = Loop( u'2100A', Properties(looptype='',repeat=u'>1',pos=u'050',req_sit=u'R',desc=u'Payer Name'), Segment( u'NM1', Properties(syntax='',req_sit=u'R',repeat=u'1',pos=u'050',desc=u'Payer Name'), Element( u'NM101', Properties(desc=u'Entity Identifier Code', req_sit=u'R', data_type=(u'ID',u'2',u'3'), position=1, codes=[u'PR'] ) ), Element( u'NM102', Properties(desc=u'Entity Type Qualifier', req_sit=u'R', data_type=(u'ID',u'1',u'1'), position=2, codes=[u'2'] ) ), Element( u'NM103', Properties(desc=u'Name Last or Organization Name', req_sit=u'R', data_type=(u'AN',u'1',u'60'), position=3, codes=[] ) ), Element( u'NM104', Properties(desc=u'Name First', req_sit=u'N', data_type=(u'AN',u'1',u'35'), position=4, codes=[] ) ), Element( u'NM105', Properties(desc=u'Name Middle', req_sit=u'N', data_type=(u'AN',u'1',u'25'), position=5,
#!/usr/bin/env python from tigershark.X12.parse import Message from tigershark.X12.parse import Loop from tigershark.X12.parse import Segment from tigershark.X12.parse import Composite from tigershark.X12.parse import Element from tigershark.X12.parse import Properties parse_278 = Message( '278', Properties(desc='278'), Loop( 'ISA', Properties(req_sit='R',repeat='1',desc='ISA'), Segment( 'ISA', Properties(), Loop( 'GS', Properties(req_sit='R',repeat='1',desc='GS'), Segment( 'GS', Properties(), Loop( 'ST', Properties(req_sit='R',repeat='1',desc='ST'), Segment( 'ST', Properties(qual=(1, '278'),req_sit='R',repeat=1,desc='Transaction Set Header'), Segment( 'BHT', Properties(req_sit='R',repeat=1,desc='Beginning of Hierarchical Transaction'), Loop( '2000A', Properties(req_sit='R',repeat='1',desc='2000A'), Segment( 'HL', Properties(qual=(3, '20'),req_sit='R',repeat='1',desc='Utilization Management Organization (UMO) Level'), Loop( '2010A', Properties(req_sit='R',repeat='>1',desc='2010A'), Segment( 'NM1', Properties(qual=(1, 'X3'),req_sit='R',repeat='1',desc='Utilization Management Organization (UMO) Name'), ), ), Loop( '2000B', Properties(req_sit='R',repeat='1',desc='2000B'), Segment( 'HL', Properties(qual=(3, '21'),req_sit='R',repeat='1',desc='Requester Level'), Loop( '2010B', Properties(req_sit='R',repeat='>1',desc='2010B'), Segment( 'NM1', Properties(qual=(1, ('1P', 'FA')),req_sit='R',repeat='1',desc='Requester Name'), Segment( 'REF', Properties(req_sit='S',repeat='8',desc='Requester Supplemental Identification'), Segment( 'N3', Properties(req_sit='S',repeat='1',desc='Requester Address'), Segment( 'N4', Properties(req_sit='S',repeat='1',desc='Requester City/State/ZIP Code'), Segment( 'PER', Properties(req_sit='S',repeat='1',desc='Requester Contact Information'), Segment( 'PRV', Properties(req_sit='S',repeat='1',desc='Requester Provider Information'),
# # Generated by TigerShark.tools.convertPyX12 on 2012-07-10 16:30:03.879137 # from tigershark.X12.parse import Message, Loop, Segment, Composite, Element, Properties parsed_841_1100 = Loop( u'1100', Properties(looptype='', repeat=u'>1', pos=u'040', req_sit=u'R', desc=u'Code List Source'), Segment( u'N1', Properties(syntax=u'R0203 P0304', req_sit=u'S', repeat=u'1', pos=u'120', desc=u'Code List Source'), Element( u'N101', Properties(desc=u'Entity Identifier Code', req_sit=u'R', data_type=(u'ID', u'2', u'3'), position=1, codes=[u'0F'])), Element( u'N102', Properties(desc=u'Name', req_sit=u'R', data_type=(u'AN', u'1', u'60'), position=2,