Coverage for src/crawler/cmds/mixed_citation.py: 95%

49 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-09-23 14:47 +0000

1""" 

2Helpers to create an xml string for mixed citations 

3 

4 

5""" 

6 

7from lxml import etree 

8from lxml.builder import E 

9from lxml.etree import Element 

10from ptf.cmds.xml.jats.jats_parser import parse_mixed_citation_into_ref 

11from ptf.cmds.xml.xml_utils import escape 

12from ptf.display.resolver import extids_formats, reverse_extids_hrefs 

13 

14 

15class GenericRefElement: 

16 name: str 

17 elements: list["str | GenericRefElement"] 

18 attributes: dict[str, str] 

19 

20 def __init__(self) -> None: 

21 super().__init__() 

22 self.elements = [] 

23 self.attributes = {} 

24 

25 def get_xml_element(self): 

26 xml_elements: list[str | Element] = [] 

27 

28 for item in self.elements: 

29 if isinstance(item, str): 

30 xml_elements.append(item) 

31 else: 

32 xml_elements.append(item.get_xml_element()) 

33 

34 return E(self.name, *xml_elements, **self.attributes) 

35 

36 def get_xml_string(self): 

37 """ 

38 Make sure the hierarchy of the objects (self.elements) is valid JATS 

39 before calling this function 

40 """ 

41 return etree.tostring(self.get_xml_element(), pretty_print=True).decode() 

42 

43 

44def find_extlink(url: str): 

45 for pattern in reverse_extids_hrefs: 

46 if url.startswith(pattern): 

47 type = reverse_extids_hrefs[pattern] 

48 content = url.removeprefix(pattern) 

49 return type, content 

50 return None, None 

51 

52 

53class ExtLinkXml(GenericRefElement): 

54 """How to use : 

55 ```py 

56 url = "https://doi.org/10.1017/S0143385700002364" 

57 extlink = ExtLinkXml(url) 

58 citation_builder.elements.append(url) 

59 ``` 

60 """ 

61 

62 name = "ext-link" 

63 

64 def __init__(self, url: str, content: str | None = None, type: str = "uri") -> None: 

65 super().__init__() 

66 

67 if not content: 67 ↛ 68line 67 didn't jump to line 68 because the condition on line 67 was never true

68 content = url 

69 

70 if type not in extids_formats: 70 ↛ 75line 70 didn't jump to line 75 because the condition on line 70 was always true

71 type_found, content_found = find_extlink(url) 

72 type = type_found or type 

73 content = content_found or content 

74 

75 self.attributes["ext-link-type"] = type 

76 self.attributes["href"] = url 

77 

78 self.elements.append(escape(content)) 

79 

80 

81class MixedCitation(GenericRefElement): 

82 """ 

83 ```py 

84 citation_builder = MixedCitation() 

85 

86 citation_builder.label = "[1]" 

87 

88 persongroup = GenericXMLTemplate() 

89 persongroup.name = "person-group" 

90 persongroup.elements.append("Michel B.") 

91 citation_builder.elements.append(persongroup) 

92 

93 citation_builder.elements.append("untagged string to put between") 

94 

95 year_builder = Year() 

96 year.elements.append("2020") 

97 citation_builder.elements.append(year) 

98 

99 mixedcitation.get_jats_ref() 

100 ``` 

101 """ 

102 

103 name = "mixed-citation" 

104 label: str | None = None 

105 

106 def get_jats_ref(self): 

107 citation_xml = self.get_xml_string() 

108 return parse_mixed_citation_into_ref(citation_xml, label=self.label)