witnesses-parser.service.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { Injectable } from '@angular/core';
  2. import { parse } from '.';
  3. import { Description, Witness, Witnesses, WitnessGroup, XMLElement } from '../../models/evt-models';
  4. import { isNestedInElem, xpath } from '../../utils/dom-utils';
  5. import { replaceNotWordChar } from '../../utils/xml-utils';
  6. import { AttributeParser } from './basic-parsers';
  7. import { GenericParserService } from './generic-parser.service';
  8. import { createParser, getID } from './parser-models';
  9. @Injectable({
  10. providedIn: 'root',
  11. })
  12. export class WitnessesParserService {
  13. private witListTagName = 'listWit';
  14. private witTagName = 'witness';
  15. private witNameAttr = 'type="siglum"';
  16. private groupTagName = 'head';
  17. private attributeParser = createParser(AttributeParser, parse);
  18. constructor(
  19. private genericParserService: GenericParserService,
  20. ) {
  21. }
  22. public parseWitnessesData(document: XMLElement): Witnesses {
  23. const lists = Array.from(document.querySelectorAll<XMLElement>(this.witListTagName));
  24. return {
  25. witnesses: this.parseWitnessesList(lists),
  26. groups: this.parseWitnessesGroups(lists),
  27. };
  28. }
  29. private parseWitnessesList(lists: XMLElement[]) {
  30. const parsedList = lists.filter((list) => !isNestedInElem(list, list.tagName))
  31. .map((list) => this.parseWitnesses(list))
  32. .reduce((x, y) => x.concat(y), []);
  33. return parsedList;
  34. }
  35. private parseWitnesses(list: XMLElement) {
  36. return Array.from(list.querySelectorAll<XMLElement>(this.witTagName))
  37. .map((wit) => this.parseWitness(wit));
  38. }
  39. private parseWitness(wit: XMLElement): Witness {
  40. const id = getID(wit);
  41. return {
  42. id,
  43. name: this.parseWitnessName(wit) || id,
  44. attributes: this.attributeParser.parse(wit),
  45. content: this.parseWitnessContent(wit),
  46. groupId: this.parseParentGroupId(wit),
  47. };
  48. }
  49. private parseWitnessName(wit: XMLElement) {
  50. // TODO use ‘?’ operator after update tu angular 9
  51. const witNameEl = wit.querySelector<XMLElement>(`*[${this.witNameAttr}]`);
  52. if (witNameEl) {
  53. return Array.from(witNameEl.childNodes)
  54. .map((child: XMLElement) => this.genericParserService.parse(child));
  55. }
  56. return witNameEl;
  57. }
  58. private parseWitnessContent(wit: XMLElement): Description {
  59. return Array.from(wit.childNodes)
  60. .filter((child) => child.nodeName !== this.witListTagName && child.textContent.trim().length !== 0)
  61. .map((child: XMLElement) => this.genericParserService.parse(child));
  62. }
  63. private parseWitnessesGroups(lists: XMLElement[]) {
  64. const parsedGroups = lists.filter((list) => isNestedInElem(list, list.tagName))
  65. .map((list) => this.parseWitnessGroup(list));
  66. return parsedGroups;
  67. }
  68. private parseWitnessGroup(list: XMLElement): WitnessGroup {
  69. return {
  70. id: list.getAttribute('xml:id') || xpath(list),
  71. name: this.parseGroupName(list) || replaceNotWordChar(list.getAttribute('xml:id')) || xpath(list),
  72. attributes: this.attributeParser.parse(list),
  73. witnesses: this.parseGroupWitnesses(list),
  74. groupId: this.parseParentGroupId(list),
  75. };
  76. }
  77. private parseGroupName(list: XMLElement) {
  78. const groupEl = Array.from(list.children)
  79. .find((child) => child.nodeName === this.groupTagName);
  80. return groupEl && groupEl.textContent;
  81. }
  82. private parseGroupWitnesses(list: XMLElement) {
  83. return Array.from(list.children)
  84. .filter(({nodeName}) => nodeName === this.witListTagName || nodeName === this.witTagName)
  85. .map((child) => child.getAttribute('xml:id'));
  86. }
  87. private parseParentGroupId(element: XMLElement) {
  88. let parentEl = element.parentElement;
  89. do {
  90. if (isNestedInElem(parentEl, this.witListTagName) && parentEl.tagName === this.witListTagName) {
  91. return parentEl.getAttribute('xml:id') || xpath(parentEl);
  92. }
  93. parentEl = parentEl.parentElement;
  94. } while (parentEl.matches(this.witListTagName));
  95. }
  96. }