Korean Statute → AKN Mapping

This document fixes the first AKN emission contract for Korean statutes. It is implemented in src/kr2akn/statute/emit.py and validated against the OASIS akomantoso30.xsd vendored under src/kr2akn/schemas/.

1. Document skeleton

<akomaNtoso
  xmlns="http://docs.oasis-open.org/legaldocml/ns/akn/3.0"
  xmlns:kr="urn:kr:akn:ext:1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://docs.oasis-open.org/legaldocml/ns/akn/3.0 akomantoso30.xsd">
  <act name="민법">
    <meta>...</meta>
    <body eId="body">...</body>
    <attachments>...</attachments>
    <components>...</components>
  </act>
</akomaNtoso>

The root element is akomaNtoso (camelCase), not akomantoso. The API object slug is elements/akomantoso, but the XSD global element is akomaNtoso.

2. Hierarchy mapping

Raw level AKN element Example eId
PART part part_1
CHAPTER chapter part_1__chp_2
SECTION section part_1__chp_2__sec_9-2
SUBSECTION subsection ...__subsec_3
HCONTAINER hcontainer ...__hc_hang_1
ARTICLE article ...__art_4-2
PARAGRAPH paragraph ...__art_4-2__para_1
POINT point ...__para_1__point_5-2
INDENT indent ...__point_1__indent_ga
  • eId is the intermediate structural path. It is unique within the act.
  • wId is added only when the raw *키 value is unique in the document. The format is {level_lower}_{source_key} (e.g. article_0001001).
  • HCONTAINER requires @name; the emitter uses "{num} {heading}".
  • num keeps the Korean display form (제4조의2, ①, 5의2., 가.).

Naming Convention notes

The NC v1.0 syntax is [prefix "__"] element_ref ["_" number]. The emitter follows it for part, chp, sec, subsec, art, para, point, and indent. Two Korean-specific extensions are intentional:

  • HCONTAINER uses the hc_ prefix because hcontainer is an AKN 3.1 addition that postdates NC v1.0.
  • Korean 목 labels are transliterated (가 → ga, 나 → na, ...) so the eId stays ASCII and URL-safe. Branches use - (가의2 → ga-2).

Content shape

  • Unit with children and intro text: <article><num/><heading/><intro><p/></intro><paragraph/>...</article>
  • Unit with children and no intro text: <article><num/><heading/><paragraph/>...</article>
  • Unit with no children: <article><num/><heading/><content><p/></content></article>
  • Empty unit: <content><p/></content> to satisfy the AKN content model.

This is why an article with direct 호 becomes article > intro + point, not article > empty paragraph > point.

3. FRBR metadata

meta/identification contains FRBRWork, FRBRExpression, and FRBRManifestation.

Level URI pattern
Work /akn/kr/act/{law_id}
Expression /akn/kr/act/{law_id}/kor@{effective_date}
Manifestation /akn/kr/act/{law_id}/kor@{effective_date}/main.xml
  • FRBRWork: FRBRthis, FRBRuri, FRBRalias*, FRBRdate+, FRBRauthor+, FRBRcountry, FRBRsubtype, FRBRnumber*, FRBRname*.
  • FRBRExpression: adds FRBRlanguage.
  • FRBRManifestation: adds FRBRformat.
  • FRBRname is the law name (not the law ID).
  • FRBRauthor href="#ministry" points to the representative ministry.
  • Dates are ISO 8601 (YYYY-MM-DD).

Annex and component documents use their own FRBR URIs:

/akn/kr/act/{law_id}/annex/{n}
/akn/kr/act/{law_id}/component/{n}

4. Korean provenance (kr: namespace)

meta/proprietary preserves fields that have no direct AKN equivalent:

<proprietary source="kr2akn">
  <kr:lawMeta lawId="001706" lawKey="..." lawName="민법"
      lawType="법률" ministry="법무부" promulgationDate="2026-03-17"
      effectiveDate="2026-03-17" rawSha256="..." ... />
  <kr:departments>
    <kr:department key="..." name="법무심의관실" ministry="법무부"
        ministryCode="1270000" contact="02-2110-3164" />
  </kr:departments>
  <kr:contactDepartment>...</kr:contactDepartment>
  <kr:extra name="편장절관">08010000</kr:extra>
</proprietary>
  • rawPath is relative to the data directory, never an absolute local path.
  • The OC key is never emitted.
  • kr: elements are allowed by the proprietary wildcard.

5. Bylaws, annexes, components

부칙

<hcontainer name="부칙" eId="hcontainer_buchik_1">
  <heading>부칙</heading>
  <content><p>...</p></content>
</hcontainer>

The current emitter preserves the bylaw text as paragraph blocks. Splitting 부칙 into article elements is a later refinement.

별표

<attachments>
  <attachment GUID="att_byulpyo_1">
    <doc name="별표 1">
      <meta>...</meta>
      <mainBody eId="mainBody_byulpyo_1">
        <heading>적용 범위</heading>
        <table eId="byulpyo_1__table_1">
          <tr eId="...__tr_1">
            <th eId="...__th_1"><p>구분</p></th>
            ...
          </tr>
        </table>
      </mainBody>
    </doc>
  </attachment>
</attachments>
  • attachment and component have no eId; use GUID.
  • doc has no eId; mainBody and table carry eId.
  • Box-drawing annex tables are parsed into <table><tr><th|td><p>.
  • The first row is emitted as <th> when the table has more than one row.
  • Merged cells are reconstructed from the box-drawing geometry:
    • a missing vertical separator inside a row becomes colspan;
    • a missing horizontal separator between rows becomes rowspan;
    • a rowspan stays anchored for every row it covers, including spans longer than two rows;
    • an empty full-width continuation line extends a full-width rowspan.
  • Both heavy (┏ ┳ ┓ ┠ ╋ ┨ ┗ ┷ ┛) and light (┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘) box-drawing families are accepted.
  • Legacy eflaw text mixes one- and two-column East Asian glyphs. When the codepoint line lengths are inconsistent, the parser switches to display-width coordinates so Korean glyphs and borders align. Annex text keeps its internal spaces; clean_text is not applied to 별표내용.
  • Nested headers that subdivide only some columns are mapped to colspan on the wider header cell. Wrapped cell lines (no horizontal rule before the next line) are merged into the previous row unless every column carries new text, which distinguishes dense coefficient tables.
  • If the geometry is still ambiguous, the parser falls back to rectangular cells rather than losing the table.

개정문 / 제개정이유

<components eId="components">
  <component GUID="cmp_component_1">
    <heading>개정문</heading>
    <doc name="개정문">
      <meta>...</meta>
      <mainBody eId="mainBody_component_1"><p>...</p></mainBody>
    </doc>
  </component>
</components>

component has no name attribute; the name lives on doc.

6. Temporal metadata

promulgationDate, effectiveDate, and per-unit effective_date are promoted from the kr: provenance into AKN lifecycle / temporalData:

<meta>
  <lifecycle source="kr2akn">
    <eventRef eId="event_20260317" date="2026-03-17"
        type="generation" source="#kr2akn"/>
  </lifecycle>
  <temporalData source="kr2akn">
    <temporalGroup eId="period_20260317">
      <timeInterval start="#event_20260317"/>
    </temporalGroup>
  </temporalData>
  ...
</meta>
<body eId="body" period="#period_20260317">...</body>
  • The document-level body carries the period of the law's effective date.
  • A unit whose effective_date differs from the law effective date carries its own period attribute and gets a separate temporalGroup.
  • timeInterval is emitted open-ended (start only) when no end date is known. If the raw XML supplies an end/repeal date (시행종료일자, 효력종료일자, 폐지일자, ... at law level or 조문시행종료일자, ... on a unit), the group id becomes period_{start}_{end}, timeInterval carries start and end, and lifecycle gets an eventRef type="repeal".
  • The original dates remain in kr:lawMeta (effectiveDate, effectiveEndDate) and on units (kr:effectiveDate, kr:effectiveEndDate) for lossless provenance.

7. Validation

kr2akn emit --all --data-dir ../data --out-dir ../data/normalized --validate
kr2akn validate --input ../data/akn/001706.akn.xml

The emitter is validated against:

  • src/kr2akn/schemas/akomantoso30.xsd (OASIS AKN 3.1, CC-BY-4.0)
  • src/kr2akn/schemas/xml.xsd

All 11 laws in the current corpus emit valid AKN. The emitter preserves the raw hierarchy counts 1:1 (article/paragraph/point/indent/heading/bylaw/annex).

8. Inline citations

Statute text is tokenized into plain text and <ref> elements. Main-law articles resolve to #eId; 부칙/개정문 use amendment-scoped references (see below).

Pattern href
「같은 법」 제N조 / 같은 법 제N조 / 이 법 #eId or the current law URI
제N조[의M][제N항][제N호][가목] #eId when the target exists
「다른 법령」 제N조 urn:kr:law-name:{percent-encoded name}
대법원 2023. 5. 18. 선고 2023다45678 판결 /akn/kr/judgment/{caseId43} when indexed, else urn:kr:case:{percent-encoded case no}
bare 제N조 in a 부칙 / 개정문 urn:kr:amendment:{law_id}:{promulgation_no}[:{bylaw_eId}]:{percent-encoded chain}
이 부칙 제N조 / 같은 부칙 제N조 #hcontainer_buchik_N__art_M when that bylaw article exists
unresolved target urn:kr:unresolved:{percent-encoded raw text}
  • The ref element carries the citation text as its content. It has no showAs attribute in AKN 3.1.
  • Annexes remain plain text. Bylaws and components now carry inline ref elements. A bare 제N조 inside a 부칙 or 개정문 often refers to the amended law or the amending instrument, not the consolidated main law, so it is emitted as an amendment-scoped reference and marked kr:refType="amendment". 이 법 / 같은 법 still resolves to the main law.
  • eId resolution supports article → paragraph → point → indent chains. Missing targets fall back to the nearest existing ancestor.

9. Bylaw articles

부칙내용 is split at 제N조(제목) boundaries into article units under hcontainer name="부칙". The raw text remains in Bylaw.text; parsed units live in Bylaw.articles.

  • Bylaw article paths are ordinal (hcontainer_buchik_1__art_1, ...art_2) because bylaw text can repeat article numbers inside amendment clauses.
  • <num> keeps the Korean number (제6조, 제7조, ...).
  • If parsing finds no articles, the emitter falls back to <content><p>.

10. Known limitations / next steps

  1. rowspan/colspan recovery is geometry based. Tables with ambiguous or missing borders fall back to rectangular cells rather than guessing. A full-width rowspan with text on every covered visual line still cannot be distinguished from a wrapped multi-line cell.
  2. timeInterval supports end dates, but the current raw eflaw corpus has no repeal/expiry fields, so all existing intervals are open-ended.
  3. Case-law (judgment) is implemented as a first pass; see docs/case-mapping.md.
  4. The court registry and case-code registry are frozen; see docs/case-codes.md. Case-code IDs are dense 9-bit ordinals and must not be renumbered.

11. Roundtrip

kr2akn akn2kr decodes an emitted act back into RawLaw. Re-emitting the decoded model produces canonically identical AKN; kr2akn roundtrip checks this for the whole corpus. The decoder reads the kr: provenance that has no AKN equivalent (unit revision type, source key, move markers, bylaw dates) and rebuilds annex tables from rowspan/colspan. See docs/roundtrip.md.