pyx12

repository·master·Indexed 41 days ago

https://github.com/azoner/pyx12

A HIPAA X12 validator, parser, and converter for ANSI X12 documents. It uses XML-based implementation guides to validate data and can generate 997/999 responses, HTML representations, or XML translations. Version 4.0.0 includes a suite of CLI tools such as x12valid, x12norm, x12html, x12info, x12xml, and xmlx12, as well as a Python API for low-level stream access, loop-aware parsing, and data modeling.

Tokens
38.9K
Snippets
123
Records
169
Agent score
51%

What's inside pyx12

  1. Overview of the pyx12 API structure

    master

    The pyx12 API is organized into several thematic groups to handle different stages of X12 processing. Depending on your goal, you will interact with different modules:

    • Reading and Writing: Use x12file for streaming reader/writer operations, x12context for context-aware parsing (iterating loops and altering children), or rawx12file for low-level stream access.
    • Data Modeling: Use segment for the segment/composite/element model and path for XPath-style references into transactions.
    • Validation: Use validation for data element type checks, codes for external code list lookups, and dataele for the normalized data element catalog.
    • Mapping: Use map_if to load/traverse implementation guides, map_index to locate maps, and map_walker to traverse map trees.
    • XML Conversion: Use x12xml or x12xml_simple for rendering X12 to XML, and xmlx12_simple for round-tripping simple XML back to X12.
    • Error Handling: Use errors for exception classes, error_handler to attach errors to the ISA/GS/ST hierarchy, and error_html for HTML error reports.
    • High-level Orchestration: Use x12n_document as the primary entry point for validating and emitting 997/999/HTML/XML, x12metadata for extracting interchange/group/transaction metadata, and params for runtime configuration.
  2. Overview of pyx12

    master

    pyx12 is a HIPAA X12 EDI document validator and converter. It is designed to parse ANSI X12N data files and validate them against an XML representation of the HIPAA Implementation Guidelines.

    Key capabilities include:

    • Validating EDI files against HIPAA guidelines.
    • Generating acknowledgement responses, specifically 997 (for 4010) or 999 (for 5010) responses.
  3. How Implementation Guide (IG) maps work

    master

    Implementation Guide maps are XML files located in pyx12/map/ that define the rules for X12 transactions (required loops, element usage, counts, and code lists). These maps drive validation, error reporting, and the context reader's traversal.

    Customizing Maps: If the bundled maps do not meet your needs (e.g., you need to validate against a newer guide or a non-HIPAA transaction):

    1. Copy the pyx12/map/ directory to a local folder.
    2. Edit or add XML map files following the existing conventions.
    3. Point pyx12 to your local directory using the map_path parameter or the --map-path / -m CLI flag.

    Map Structure: The XML map is a tree of <loop>, <segment>, <element>, and <composite> nodes. Example segment definition:

    <segment xid="NM1">
      <name>Subscriber Name</name>
      <usage>R</usage>          <!-- R=required, S=situational, N=not used -->
      <pos>015</pos>             <!-- ordinal within parent loop -->
      <max_use>1</max_use>       <!-- max times this segment may repeat -->
      <element xid="NM101">
        <data_ele>98</data_ele>  <!-- look up type/length in dataele.xml -->
        <usage>R</usage>
        <valid_codes>
          <code>IL</code>
        </valid_codes>
      </element>
    </segment>
    <segment xid="NM1">
      <name>Subscriber Name</name>
      <usage>R</usage>          <!-- R=required, S=situational, N=not used -->
      <pos>015</pos>             <!-- ordinal within parent loop -->
      <max_use>1</max_use>       <!-- max times this segment may repeat -->
      <element xid="NM101">
        <data_ele>98</data_ele>  <!-- look up type/length in dataele.xml -->
        <usage>R</usage>
        <valid_codes>
          <code>IL</code>
        </valid_codes>
      </element>
    </segment>
  4. Understand the X12 hierarchy in pyx12

    master

    pyx12 mirrors the standard X12 EDI document hierarchy. Understanding this hierarchy is essential for navigating error reports, the context reader's tree, and generating 997/999 acknowledgements. The layers are:

    1. Interchange (ISA … IEA): The outermost envelope containing sender/receiver info and control numbers.
    2. Functional group (GS … GE): Groups transactions of the same type.
    3. Transaction set (ST … SE): A single business document (e.g., an 837 claim).
    4. Loops and segments: The body of the transaction. A segment is a single line; a loop is a named group of segments/sub-loops defined by the Implementation Guide.
    5. Elements and composites: Fields within a segment. Elements are separated by *; composites are multi-part fields with sub-parts separated by :.
  5. Transform X12 into JSON using path expressions

    master

    To convert complex X12 files (like an 834 enrollment) into structured JSON, use the transformation pattern.

    Instead of writing manual scaffolding for every segment, use X12 path expressions against a context node to extract values from deeply nested loops. This allows you to pull data directly into OrderedDict objects which can then be serialized via json.dumps.

    Common path patterns include:

    • 2100A/NM109 (Member Name)
    • DTP[356]03 (Date/Time Reference)
    • REF[0F]02 (Identifier)

    A typical pipeline involves wrapping pyx12.x12context.X12ContextReader in a custom parser class that dispatches on datatree.id to capture envelope state (ISA/GS/ST) and descends into specific loops (like 2000 members) to build the JSON structure.

    # Concept based on 834_x12_json.py
    # Use path expressions to extract nested data
    member_name = node.get_value("2100A/NM109")
    ref_value = node.get_value("REF[0F]02")
  6. Reference Pyx12 error code namespaces

    master

    Pyx12 uses an internal error code namespace following the convention <LEVEL>_<X12_CODE>_<descriptor>.

    • LEVEL: ELE (Element), COMP (Composite), or SEG (Segment).
    • X12_CODE: The AK4/IK4/AK3/IK3 code the visitor will emit in the 997/999 acknowledgement.
    • descriptor: A snake_case discriminator used to distinguish multiple pyx12 codes that map to the same X12 code (e.g., multiple element-level checks mapping to AK/IK "6").

    These codes are available in the err_cde field of EleError, SegError, and entries in the errh_list. In JSON output, they are paired with an x12_code field containing the dereferenced X12 code.

  7. Understand the Error Handling mechanism

    master

    Errors found by the walker, reader, or validator are recorded against an error handler. There are two main types:

    1. pyx12.error_handler.err_handler: A tree-shaped handler that mirrors the X12 hierarchy (ROOT → ISA → GS → ST → segment → element). This is used by 997/999 generators to emit acknowledgement segments (e.g., AK3 for segment errors, AK4 for element errors).
    2. pyx12.error_handler.errh_list: A flat list of errors per level, which is easier for programmatic access and inspection.

    Errors are recorded as the walker traverses the document, allowing for the generation of formal X12 acknowledgements.

  8. Understand how X12 maps are identified and indexed

    master

    Pyx12 uses XML maps located in pyx12/map/ to validate transactions. Maps are named using the pattern <transaction>.<version>.<X-number>[.A<n>].xml (e.g., 834.4010.X095.A1.xml).

    At runtime, Pyx12 consults pyx12/map/maps.xml to bind a triple of identifiers to a map file. The identifiers are:

    NameAbbreviationX12 Element
    Interchange Control Version NumberICVNISA12
    Version / Release / Industry Identifier CodeVRIICGS08
    Functional Identifier CodeFICGS01
    Transaction Set Purpose Code (for 278)TSPCBHT02
  9. How errors are surfaced in Pyx12

    master

    When validating an X12 document, Pyx12 records problems at five distinct levels. The top-level validator (x12valid or pyx12.x12n_document.x1n_document) returns False if any errors are found, generates a 997/999 acknowledgement, and logs human-readable messages.

    For programmatic access to individual errors, use pyx12.x12file.X12Reader or pyx12.x12context.X12ContextReader with a custom handler. The errh_list collects errors into per-level lists that can be iterated directly.

    LevelPyx12 method997 / 999 segment
    Interchange (ISA)isa_errorTA1 (interchange ack)
    Functional Groupgs_errorAK9
    Transaction Setst_errorAK5 / IK5
    Segmentseg_errorAK3 / IK3
    Element / sub-eleele_errorAK4 / IK4
  10. Understand X12 Mapping Rules and Loop Inheritance

    master

    When working with X12 maps in pyx12, be aware of the following structural and inheritance rules:

    • Loop Inheritance: Loops inherit the Implementation Guide (IG) usage from their first child segment. Consequently, the first child segment of a loop is effectively required.
    • Segment Placement: For specific implementations like the 834, ensure the ST and SE segments are moved to be direct children of the ST_LOOP.
    • Loop Structure: For 837 maps, the 2300 loop should be copied to be a child of both 2000B and 2000C.
    • Wrapper Loops: Check if the map expects fixed wrapper loops, typically categorized as HEADER, DETAIL, or FOOTER.
  11. Mutate X12 segments using the X12DataNode mutation pattern

    master

    To modify or 'de-identify' an X12 file (e.g., replacing PHI like names or SSNs with synthetic values), use the mutation pattern.

    By parsing the file with a context reader, you can use pyx12.x12context.X12DataNode.set_value to patch element values in place. You address elements using X12 path expressions, such as:

    • 2100A/NM103 (to target a member's last name)
    • REF[0F]02 (to target a specific subscriber identifier)

    After mutation, use pyx12.x12file.X12Writer to write the transformed stream back to disk.

    # Example path-based mutation
    # node is an X12DataNode
    node.set_value("2100A/NM103", "SYNTHETIC_NAME")
    node.set_value("REF[0F]02", "000-00-0000")