diff --git a/profile-merger/profile-merger-1.0-SNAPSHOT.jar b/profile-merger/profile-merger-1.0-SNAPSHOT.jar index 3bdc306..be75ea1 100644 Binary files a/profile-merger/profile-merger-1.0-SNAPSHOT.jar and b/profile-merger/profile-merger-1.0-SNAPSHOT.jar differ diff --git a/profile-merger/src/main/java/org/verapdf/ProfileMerger.java b/profile-merger/src/main/java/org/verapdf/ProfileMerger.java index 4363477..437557e 100644 --- a/profile-merger/src/main/java/org/verapdf/ProfileMerger.java +++ b/profile-merger/src/main/java/org/verapdf/ProfileMerger.java @@ -72,13 +72,15 @@ private static void updatePDFUAProfiles(ZipFile zipSource) { new File(PDFUA_FOLDER).mkdirs(); generateProfile(zipSource, "PDFUA-1.xml", PDFUA_FOLDER, new String[]{"1"}, new String[]{}, Collections.emptyList()); generateProfile(zipSource, "PDFUA-2.xml", PDFUA_FOLDER, new String[]{"2"}, new String[]{}, Collections.emptyList()); - List excludedTaggedRules = new ArrayList<>(6); + List excludedTaggedRules = new ArrayList<>(8); excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 1)); - excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 1656)); - excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 1657)); - excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 1658)); - excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 1659)); - excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 1660)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 2)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 3)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 4)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 5)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 6)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 7)); + excludedTaggedRules.add(Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", 8)); generateProfile(zipSource, "PDFUA-2-ISO32005.xml", PDFUA_FOLDER, new String[]{"2"}, new String[]{"ISO-32005-Tagged.xml"}, excludedTaggedRules); generateProfile(zipSource, "WCAG-2-2.xml", PDFUA_FOLDER, new String[]{"WCAG/2.2"}, new String[]{}, Collections.emptyList()); List excludedWCAGRules = new ArrayList<>(7); diff --git a/tagged-structure-merger/pom.xml b/tagged-structure-merger/pom.xml index 56455c6..57c384c 100644 --- a/tagged-structure-merger/pom.xml +++ b/tagged-structure-merger/pom.xml @@ -29,6 +29,16 @@ + + + + src/main/resources + + rules.csv + + + + diff --git a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/Cli.java b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/Cli.java index c351124..d5d11e1 100644 --- a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/Cli.java +++ b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/Cli.java @@ -41,16 +41,14 @@ public static void main(final String[] args) throws IOException, JAXBException { System.exit(0); } - if (cliArgParser.getCsvPath() != null) { - CliProcessor processor = CliProcessor.createProcessorFromArgs(cliArgParser); - String outputPath = cliArgParser.getOutputPath(); - if (outputPath != null) { - try (OutputStream out = new FileOutputStream(new File(outputPath))) { - processor.process(cliArgParser.getCsvPath(), out); - } - } else { - processor.process(cliArgParser.getCsvPath(), System.out); + CliProcessor processor = CliProcessor.createProcessorFromArgs(cliArgParser); + String outputPath = cliArgParser.getOutputPath(); + if (outputPath != null) { + try (OutputStream out = new FileOutputStream(new File(outputPath))) { + processor.process(cliArgParser.getCsvPath(), out); } + } else { + processor.process(cliArgParser.getCsvPath(), System.out); } } } diff --git a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliArgParser.java b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliArgParser.java index 25ab7d7..eb196c6 100644 --- a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliArgParser.java +++ b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliArgParser.java @@ -42,7 +42,7 @@ public class CliArgParser { @Parameter(names = { PROFILE_CREATOR }, description = "The creator of generated profile") private String creator = "veraPDF Consortium"; - @Parameter(description = "INPUT_CSV", required = true) + @Parameter(description = "INPUT_CSV", required = false) private List csvPath = null; /** * @return true if help requested @@ -75,7 +75,7 @@ public String getOutputPath() { * @return the list of file paths */ public String getCsvPath() { - return this.csvPath.get(0); + return this.csvPath != null ? this.csvPath.get(0) : null; } diff --git a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliProcessor.java b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliProcessor.java index c62e7a2..e615cb8 100644 --- a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliProcessor.java +++ b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/CliProcessor.java @@ -32,21 +32,26 @@ static CliProcessor createProcessorFromArgs(final CliArgParser args) { void process(String csvIn, OutputStream out) throws FileNotFoundException, JAXBException { List relations = parseRelations(csvIn); - SortedSet rules = new TreeSet<>(new Profiles.RuleComparator()); SortedSet variables = new TreeSet<>(Comparator.comparing(Variable::getName)); - - rules.addAll(ruleCreator.generateRules(relations)); - + + SortedSet rules = ruleCreator.generateRules(relations); ProfileDetails det = Profiles.profileDetailsFromValues(name, description, creator, new Date()); ValidationProfile mergedProfile = Profiles.profileFromSortedValues(ruleCreator.getFlavour(), det, "", rules, variables); Profiles.profileToXml(mergedProfile, out, true, false); } + + private static Scanner getScanner(String csvIn) throws FileNotFoundException { + if (csvIn != null) { + return new Scanner(new File(csvIn)); + } + return new Scanner(CliProcessor.class.getClassLoader().getResourceAsStream("rules.csv")); + } private List parseRelations(String csvIn) throws FileNotFoundException { List res = new ArrayList<>(); - try (Scanner sc = new Scanner(new File(csvIn))) { + try (Scanner sc = getScanner(csvIn)) { // read and check headers - String[] headers = sc.nextLine().split(","); + String[] headers = sc.nextLine().split(";"); if (!"".equals(headers[0])) { throw new IllegalArgumentException("Invalid headers format"); } @@ -55,7 +60,7 @@ private List parseRelations(String csvIn) throws FileNo int childIndex = 0; while (sc.hasNextLine()) { ++childIndex; - String[] children = sc.nextLine().split(","); + String[] children = sc.nextLine().split(";"); // is this line correct, probably add first element check on containing in standard types set if (children.length != headers.length || "".equals(children[0])) { continue; diff --git a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/StructureRuleCreator.java b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/StructureRuleCreator.java index 394eea5..473afab 100644 --- a/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/StructureRuleCreator.java +++ b/tagged-structure-merger/src/main/java/org/verapdf/tools/tagged/StructureRuleCreator.java @@ -58,16 +58,21 @@ public PDFAFlavour getFlavour() { return this.flavour; } - public List generateRules(List relations) { - List res = new ArrayList<>(relations.size()); + public SortedSet generateRules(List relations) { + SortedSet res = new TreeSet<>(new Profiles.RuleComparator()); int testNumber = 0; // standard structure type requirement List annex_l_reference = Collections.singletonList(Profiles.referenceFromValues( this.pdfVersion.getIso(), "Annex_L")); - res.add(getRuleAboutNotRemappedNonStandardType(annex_l_reference, ++testNumber)); - + res.add(getRuleAboutCircularMapping(annex_l_reference, ++testNumber)); + res.add(getRuleAboutRemappedStandardType(annex_l_reference, ++testNumber)); + res.add(getRuleAboutStructTreeRoot(annex_l_reference, ++testNumber)); + res.add(getRuleAboutStructElementParent(annex_l_reference, ++testNumber)); + res.add(getRuleAboutMathMLParent(annex_l_reference, ++testNumber)); + res.add(getRuleAboutRuby(annex_l_reference, ++testNumber)); + res.add(getRuleAboutWarichu(annex_l_reference, ++testNumber)); for (ParsedRelationStructure relation : relations) { if (shallProcess(relation)) { RuleData data = getRuleData(relation); @@ -75,20 +80,20 @@ public List generateRules(List relations) { System.err.println("Missing rule for " + relation.getDescriptionString()); continue; } - RuleId id = Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", ++testNumber); + RuleId id = Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, + getClause(relation), 1); ErrorDetails error = Profiles.errorFromValues(data.errorMessage, Collections.emptyList()); res.add(Profiles.ruleFromValues(id, data.object, null, StructureTag.getTags(relation), data.description, data.test, error, annex_l_reference)); } } - res.add(getRuleAboutCircularMapping(annex_l_reference, ++testNumber)); - res.add(getRuleAboutRemappedStandardType(annex_l_reference, ++testNumber)); - res.add(getRuleAboutStructTreeRoot(annex_l_reference, ++testNumber)); - res.add(getRuleAboutStructElementParent(annex_l_reference, ++testNumber)); - res.add(getRuleAboutMathMLParent(annex_l_reference, ++testNumber)); return res; } + private static String getClause(ParsedRelationStructure relation) { + return relation.getParent() + "-" + (CONTENT_ITEM.equals(relation.getChild()) ? "content" : relation.getChild()); + } + private Rule getRuleAboutNotRemappedNonStandardType(List annex_l_reference, int testNumber) { return Profiles.ruleFromValues( Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", testNumber), @@ -153,6 +158,32 @@ private Rule getRuleAboutMathMLParent(List annex_l_reference, int tes annex_l_reference); } + private Rule getRuleAboutRuby(List annex_l_reference, int testNumber) { + return Profiles.ruleFromValues( + Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", testNumber), + "SERuby", + null, + StructureTag.STRUCTURE_TAG.getTag(), + "A Ruby structure element shall contain a single RB structure element and a single RT structure element or a Ruby structure element shall consist of a four-element subsequence: RB, RP, RT, RP", + "kidsStandardTypes == 'RB&RT' || kidsStandardTypes == 'RB&RP&RT&RP'", + Profiles.errorFromValues("The Ruby structure element has invalid sequence of children: %1", + Collections.singletonList(ErrorArgumentImpl.fromValues("kidsStandardTypes.replaceAll('&', ',')", null, null))), + annex_l_reference); + } + + private Rule getRuleAboutWarichu(List annex_l_reference, int testNumber) { + return Profiles.ruleFromValues( + Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", testNumber), + "SEWarichu", + null, + StructureTag.STRUCTURE_TAG.getTag(), + "Content typeset as warichu shall be tagged in a three-element sequence consisting of the structure elements WP, WT and WP, grouped inside a Warichu structure element", + "kidsStandardTypes == 'WP&WT&WP'", + Profiles.errorFromValues("The Warichu structure element has invalid sequence of children: %1", + Collections.singletonList(ErrorArgumentImpl.fromValues("kidsStandardTypes.replaceAll('&', ',')", null, null))), + annex_l_reference); + } + private Rule getRuleAboutStructTreeRoot(List annex_l_reference, int testNumber) { return Profiles.ruleFromValues( Profiles.ruleIdFromValues(PDFAFlavour.Specification.ISO_32005, "6.2", testNumber), diff --git a/tagged-structure-merger/src/main/resources/rules.csv b/tagged-structure-merger/src/main/resources/rules.csv new file mode 100644 index 0000000..2813e68 --- /dev/null +++ b/tagged-structure-merger/src/main/resources/rules.csv @@ -0,0 +1,54 @@ +;StructTreeRoot;Document;DocumentFragment;Part;Div;Art;Sect;TOC;TOCI;Aside;BlockQuote;NonStruct;Private;Title;Sub;P;Note;Code;Hn;H;Lbl;Em;Strong;Span;Quote;Link;Reference;Annot;Form;Ruby;RB;RT;RP;Warichu;WT;WP;FENote;Index;L;LI;LBody;BibEntry;Table;TR;TH;TD;THead;TBody;TFoot;Caption;Figure;Formula;Artifact +Document;1;0..n;0..n;‡;‡;∅;∅;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +DocumentFragment;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;∅*;∅*;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅;0..n +Part;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅*;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;0..n;0..n +Art;∅;0..n;0..n;‡;‡;∅;0..n;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;0..n;∅;0..1;0..1;∅;∅;∅;∅;∅;0..n;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;∅;0..n +Div;∅;0..n;0..n;‡;‡;0..n;0..n;∅;0..n;0..n;0..n;‡;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;0..n;∅;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Sect;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;0..n;∅;0..1;0..1;∅;∅;∅;∅;∅;0..n;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;∅;0..n +TOC;∅;0..n;0..n;‡;‡;0..n;0..n;0..n;0..n;0..n;0..n;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +TOCI;∅;∅;∅;‡;‡;∅;∅;0..n;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +Aside;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;∅;∅;‡;0..n;0..n;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;0..n;0..n +BlockQuote;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;0..n;0..n +NonStruct;∅;0..n;0..n;‡;‡;0..n;0..n;0..n;0..n;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n +Private;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n +P;∅;0..n;0..n;‡;‡;0..n;0..n;∅;0..n;0..n;0..n;‡;0..n;0..n;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Note;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Code;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;∅*;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Hn;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +H;∅;0..1;0..1;‡;‡;0..1;0..1;∅;∅;0..1;0..1;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;0..1;∅;∅;∅;0..1;0..1;∅;∅;∅;0..1;0..1;0..1;0..1 +Title;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +Sub;∅;∅;∅;‡;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅*;0..n;0..n +Lbl;∅;∅;∅;‡;‡;0..n;0..n;∅;0..n;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;0..n;∅;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Em;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Strong;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Span;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Quote;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Link;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Reference;∅;∅;∅;‡;‡;∅;∅;∅;0..n;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅*;∅*;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Annot;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Form;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅*;∅;∅*;∅;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Ruby;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +RB;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;[a];∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +RT;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;[a];∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +RP;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;[a];∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +Warichu;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +WT;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;[b];∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +WP;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;[b];∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +FENote;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Index;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +L;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅*;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;0..n;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +LI;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +LBody;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +BibEntry;∅;∅;∅;‡;‡;∅;∅;∅;∅;∅;∅;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Table;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;∅;0..n;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;∅*;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +TR;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;0..n;0..n;0..n;∅;∅;∅;0..n +TH;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n +TD;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;0..n +THead;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..1;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +TBody;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +TFoot;∅;∅;∅;∅;‡;∅;∅;∅;∅;∅;∅;‡;0..n;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..1;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n +Caption;∅;∅;∅;‡;‡;0..n;0..n;0..1;∅;0..1;0..1;‡;0..n;0..1;∅;∅;∅*;∅;∅;∅;∅;∅;∅;∅;∅;∅*;∅;∅*;0..1;∅;∅;∅;∅;∅;∅;∅;∅*;0..n;0..1;∅;0..1;∅;0..1;∅;∅;∅;∅;∅;∅;∅;0..1;0..1;0..1 +Figure;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅*;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Formula;∅;0..n;0..n;‡;‡;0..n;0..n;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;∅*;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;∅;∅;0..n;∅;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n +Artifact;∅;0..n;0..n;‡;‡;0..n;0..n;0..n;0..n;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;∅;0..n;0..n;0..n;∅;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n +content item;∅;∅;∅;∅;∅;∅;∅;∅;∅;0..n;0..n;‡;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;0..n;‡;‡;‡;0..n;‡;‡;0..n;∅;∅;0..n;0..n;0..n;∅;∅;0..n;0..n;∅;∅;∅;0..n;0..n;0..n;0..n