ds-caselaw-marklogic-api-client 27.0.1__py3-none-any.whl → 27.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ds-caselaw-marklogic-api-client might be problematic. Click here for more details.

caselawclient/Client.py CHANGED
@@ -634,12 +634,14 @@ class MarklogicApiClient:
634
634
  judgment_uri: DocumentURIString,
635
635
  annotation: str = "",
636
636
  expires_at_midnight: bool = False,
637
+ timeout_seconds: int = -1,
637
638
  ) -> requests.Response:
639
+ """If timeout_seconds is -1, the lock never times out"""
638
640
  uri = self._format_uri_for_marklogic(judgment_uri)
639
641
  vars: query_dicts.CheckoutJudgmentDict = {
640
642
  "uri": uri,
641
643
  "annotation": annotation,
642
- "timeout": -1,
644
+ "timeout": timeout_seconds,
643
645
  }
644
646
 
645
647
  if expires_at_midnight:
@@ -1,5 +1,5 @@
1
1
  import datetime
2
- from typing import Any, Optional, cast
2
+ from typing import Any, Optional
3
3
  from unittest.mock import Mock
4
4
 
5
5
  from typing_extensions import TypeAlias
@@ -75,55 +75,24 @@ class DocumentFactory:
75
75
 
76
76
 
77
77
  class JudgmentFactory(DocumentFactory):
78
- target_class = Judgment
79
-
80
- def __init__(self) -> None:
81
- self.PARAMS_MAP = self.PARAMS_MAP | {
82
- "neutral_citation": "[2023] Test 123",
83
- "best_human_identifier": "[2023] Test 123",
84
- }
85
-
86
- super().__init__()
87
-
88
- @classmethod
89
- def build(
90
- cls,
91
- uri: str = "test/2023/123",
92
- html: str = "<p>This is a judgment.</p>",
93
- api_client: Optional[MarklogicApiClient] = None,
94
- **kwargs: Any,
95
- ) -> Judgment:
96
- return cast(Judgment, super().build(uri, html, api_client, **kwargs))
78
+ target_class: TypeAlias = Judgment
79
+ PARAMS_MAP = DocumentFactory.PARAMS_MAP | {
80
+ "neutral_citation": "[2023] Test 123",
81
+ }
97
82
 
98
83
 
99
84
  class PressSummaryFactory(DocumentFactory):
100
- target_class = PressSummary
101
-
102
- def __init__(self) -> None:
103
- self.PARAMS_MAP = self.PARAMS_MAP | {
104
- "neutral_citation": "[2023] Test 123",
105
- "best_human_identifier": "[2023] Test 123",
106
- }
107
-
108
- super().__init__()
109
-
110
- @classmethod
111
- def build(
112
- cls,
113
- uri: str = "test/2023/123/press-summary/1",
114
- html: str = "<p>This is a judgment.</p>",
115
- api_client: Optional[MarklogicApiClient] = None,
116
- **kwargs: Any,
117
- ) -> PressSummary:
118
- return cast(PressSummary, super().build(uri, html, api_client, **kwargs))
85
+ target_class: TypeAlias = PressSummary
86
+ PARAMS_MAP = DocumentFactory.PARAMS_MAP | {
87
+ "neutral_citation": "[2023] Test 123",
88
+ }
119
89
 
120
90
 
121
91
  class SimpleFactory:
92
+ target_class: TypeAlias = object
122
93
  # "name_of_attribute": "default value"
123
94
  PARAMS_MAP: dict[str, Any]
124
95
 
125
- target_class: TypeAlias = object
126
-
127
96
  @classmethod
128
97
  def build(cls, **kwargs: Any) -> target_class:
129
98
  mock_object = Mock(spec=cls.target_class, autospec=True)
@@ -145,6 +114,7 @@ class SearchResultMetadataFactory(SimpleFactory):
145
114
  "author_email": "fake.email@gov.invalid",
146
115
  "consignment_reference": "TDR-2023-ABC",
147
116
  "submission_datetime": datetime.datetime(2023, 2, 3, 9, 12, 34),
117
+ "editor_status": "New",
148
118
  }
149
119
 
150
120
 
@@ -495,3 +495,10 @@ class Document:
495
495
  Is it sensible to reparse this document?
496
496
  """
497
497
  return self.docx_exists()
498
+
499
+ def __getattr__(self, name: str) -> Any:
500
+ warnings.warn(f"{name} no longer exists on Document, using Document.body instead", DeprecationWarning)
501
+ try:
502
+ return getattr(self.body, name)
503
+ except Exception:
504
+ raise AttributeError(f"Neither 'Document' nor 'DocumentBody' objects have an attribute '{name}'")
@@ -1,10 +1,12 @@
1
1
  import datetime
2
+ import os
2
3
  import warnings
3
- from functools import cached_property
4
+ from functools import cache, cached_property
4
5
  from typing import Optional
5
6
 
6
7
  import pytz
7
8
  from ds_caselaw_utils.types import CourtCode
9
+ from saxonche import PySaxonProcessor
8
10
 
9
11
  from caselawclient.models.utilities.dates import parse_string_date_as_utc
10
12
 
@@ -129,6 +131,23 @@ class DocumentBody:
129
131
  def content_as_xml(self) -> str:
130
132
  return self._xml.xml_as_string
131
133
 
134
+ @cache
135
+ def content_as_html(self, image_base_url: Optional[str] = None) -> str:
136
+ """Convert the XML representation of the Document into HTML for rendering."""
137
+
138
+ html_xslt_location = os.path.join(os.path.dirname(os.path.realpath(__file__)), "transforms", "html.xsl")
139
+
140
+ with PySaxonProcessor() as proc:
141
+ xslt_processor = proc.new_xslt30_processor()
142
+ document = proc.parse_xml(xml_text=self._xml.xml_as_string)
143
+
144
+ executable = xslt_processor.compile_stylesheet(stylesheet_file=html_xslt_location)
145
+
146
+ if image_base_url:
147
+ executable.set_parameter("image-base", proc.make_string_value(image_base_url))
148
+
149
+ return str(executable.transform_to_string(xdm_node=document))
150
+
132
151
  @cached_property
133
152
  def failed_to_parse(self) -> bool:
134
153
  """
@@ -0,0 +1,1062 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
4
+ xpath-default-namespace="http://docs.oasis-open.org/legaldocml/ns/akn/3.0"
5
+ xmlns:uk="https://caselaw.nationalarchives.gov.uk/akn"
6
+ xmlns:html="http://www.w3.org/1999/xhtml"
7
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
8
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
9
+ exclude-result-prefixes="uk html math xs">
10
+
11
+ <xsl:output method="html" encoding="utf-8" indent="no" include-content-type="no" />
12
+
13
+ <xsl:strip-space elements="*" />
14
+ <xsl:preserve-space elements="p block num heading span a courtType date docDate docTitle docketNumber judge lawyer location neutralCitation party role time" />
15
+
16
+ <xsl:param name="image-base" as="xs:string" select="'https://assets.caselaw.nationalarchives.gov.uk/'" />
17
+
18
+ <xsl:function name="uk:link-is-supported" as="xs:boolean">
19
+ <xsl:param name="href" as="attribute()?" />
20
+ <xsl:choose>
21
+ <xsl:when test="$href='#'">
22
+ <xsl:sequence select="false()" />
23
+ </xsl:when>
24
+ <xsl:when test="starts-with($href, '#')">
25
+ <xsl:sequence select="true()" />
26
+ </xsl:when>
27
+ <xsl:when test="starts-with($href, 'https://www.legislation.gov.uk/')">
28
+ <xsl:sequence select="true()" />
29
+ </xsl:when>
30
+ <xsl:when test="starts-with($href, 'http://www.legislation.gov.uk/')">
31
+ <xsl:sequence select="true()" />
32
+ </xsl:when>
33
+ <xsl:when test="starts-with($href, 'https://caselaw.nationalarchives.gov.uk/')">
34
+ <xsl:variable name="components" as="xs:string*" select="tokenize(substring-after($href, 'https://caselaw.nationalarchives.gov.uk/'), '/')" />
35
+ <xsl:choose>
36
+ <xsl:when test="empty($components[3])">
37
+ <xsl:sequence select="false()" />
38
+ </xsl:when>
39
+ <xsl:when test="$components[1] = ('uksc', 'ukpc')">
40
+ <xsl:sequence select="$components[2] ge '2014'" />
41
+ </xsl:when>
42
+ <xsl:when test="$components[1] = ('ewca', 'ewhc')">
43
+ <xsl:sequence select="$components[3] ge '2003'" />
44
+ </xsl:when>
45
+ <xsl:when test="$components[1] = 'ewcop'">
46
+ <xsl:sequence select="$components[2] ge '2009'" />
47
+ </xsl:when>
48
+ <xsl:when test="$components[1] = 'ewfc'">
49
+ <xsl:sequence select="$components[2] ge '2014'" />
50
+ </xsl:when>
51
+ <xsl:when test="$components[1] = 'ukut'">
52
+ <xsl:choose>
53
+ <xsl:when test="$components[2] = 'iac'">
54
+ <xsl:sequence select="$components[3] ge '2010'" />
55
+ </xsl:when>
56
+ <xsl:when test="$components[2] = 'lc'">
57
+ <xsl:sequence select="$components[3] ge '2015'" />
58
+ </xsl:when>
59
+ <xsl:when test="$components[2] = 'tcc'">
60
+ <xsl:sequence select="$components[3] ge '2017'" />
61
+ </xsl:when>
62
+ <xsl:otherwise>
63
+ <xsl:sequence select="false()" />
64
+ </xsl:otherwise>
65
+ </xsl:choose>
66
+ </xsl:when>
67
+ <xsl:otherwise>
68
+ <xsl:sequence select="false()" />
69
+ </xsl:otherwise>
70
+ </xsl:choose>
71
+ </xsl:when>
72
+ <xsl:otherwise>
73
+ <xsl:sequence select="false()" />
74
+ </xsl:otherwise>
75
+ </xsl:choose>
76
+ </xsl:function>
77
+
78
+ <xsl:variable name="doc-id" as="xs:string">
79
+ <xsl:variable name="work-uri" as="xs:string">
80
+ <xsl:sequence select="/akomaNtoso/*/meta/identification/FRBRWork/FRBRthis/@value" />
81
+ </xsl:variable>
82
+ <xsl:variable name="long-form-prefix" as="xs:string" select="'https://caselaw.nationalarchives.gov.uk/id/'" />
83
+ <xsl:choose>
84
+ <xsl:when test="starts-with($work-uri, $long-form-prefix)">
85
+ <xsl:sequence select="substring-after($work-uri, $long-form-prefix)" />
86
+ </xsl:when>
87
+ <xsl:otherwise>
88
+ <xsl:sequence select="$work-uri" />
89
+ </xsl:otherwise>
90
+ </xsl:choose>
91
+ </xsl:variable>
92
+
93
+ <xsl:template match="meta" />
94
+
95
+ <xsl:template match="judgment">
96
+ <article class="judgment">
97
+ <xsl:apply-templates />
98
+ <xsl:apply-templates select="attachments/attachment/doc[@name=('annex','schedule')]" />
99
+ <xsl:call-template name="footnotes">
100
+ <xsl:with-param name="footnotes" as="element()*">
101
+ <xsl:sequence select="header//authorialNote" />
102
+ <xsl:sequence select="judgmentBody//authorialNote" />
103
+ <xsl:sequence select="attachments/attachment/doc[@name=('annex','schedule')]//authorialNote" />
104
+ </xsl:with-param>
105
+ </xsl:call-template>
106
+ <xsl:apply-templates select="attachments/attachment/doc[not(@name=('annex','schedule'))]" />
107
+ </article>
108
+ </xsl:template>
109
+
110
+ <!-- for press summaries, priority needed to trump attachment template -->
111
+ <xsl:template match="/akomaNtoso/doc" priority="1">
112
+ <article class="judgment">
113
+ <xsl:apply-templates />
114
+ <xsl:call-template name="footnotes" />
115
+ </article>
116
+ </xsl:template>
117
+
118
+ <xsl:template match="attachments" />
119
+
120
+ <xsl:template match="coverPage | header | preface">
121
+ <header class="judgment-header">
122
+ <xsl:apply-templates />
123
+ </header>
124
+ </xsl:template>
125
+
126
+ <xsl:template match="judgmentBody | doc[@name='pressSummary']/mainBody" priority="1">
127
+ <section class="judgment-body">
128
+ <xsl:apply-templates />
129
+ </section>
130
+ </xsl:template>
131
+
132
+ <xsl:template match="doc[@name=('annex','schedule')]">
133
+ <section>
134
+ <xsl:apply-templates />
135
+ </section>
136
+ </xsl:template>
137
+
138
+ <xsl:template match="doc[not(@name=('annex','schedule'))]">
139
+ <section>
140
+ <xsl:apply-templates />
141
+ <xsl:call-template name="footnotes" />
142
+ </section>
143
+ </xsl:template>
144
+
145
+ <xsl:template match="doc[not(@name=('annex','schedule'))]/mainBody">
146
+ <div>
147
+ <xsl:apply-templates />
148
+ </div>
149
+ </xsl:template>
150
+
151
+ <xsl:template match="decision">
152
+ <xsl:choose>
153
+ <xsl:when test="exists(preceding-sibling::*) or exists(following-sibling::*)">
154
+ <section>
155
+ <xsl:apply-templates />
156
+ </section>
157
+ </xsl:when>
158
+ <xsl:otherwise>
159
+ <xsl:next-match />
160
+ </xsl:otherwise>
161
+ </xsl:choose>
162
+ </xsl:template>
163
+
164
+ <xsl:template match="level">
165
+ <section>
166
+ <xsl:apply-templates select="@eId" />
167
+ <xsl:if test="num | heading">
168
+ <p>
169
+ <xsl:apply-templates select="num | heading" />
170
+ </p>
171
+ </xsl:if>
172
+ <xsl:apply-templates select="* except (num, heading)" />
173
+ </section>
174
+ </xsl:template>
175
+
176
+ <xsl:template match="level/num">
177
+ <span style="display:inline-block;min-width:0.5in">
178
+ <xsl:call-template name="inline" />
179
+ </span>
180
+ </xsl:template>
181
+
182
+ <xsl:template match="paragraph">
183
+ <section class="judgment-body__section">
184
+ <xsl:apply-templates select="@eId" />
185
+ <span class="judgment-body__number">
186
+ <xsl:apply-templates select="num" />
187
+ </span>
188
+ <div>
189
+ <xsl:apply-templates select="* except num" />
190
+ </div>
191
+ </section>
192
+ </xsl:template>
193
+
194
+ <xsl:template match="level/@eId | paragraph/@eId">
195
+ <xsl:attribute name="id">
196
+ <xsl:sequence select="." />
197
+ </xsl:attribute>
198
+ </xsl:template>
199
+
200
+ <xsl:template match="subparagraph">
201
+ <section class="judgment-body__nested-section">
202
+ <span class="judgment-body__number">
203
+ <xsl:apply-templates select="num" />
204
+ </span>
205
+ <div>
206
+ <xsl:apply-templates select="* except num" />
207
+ </div>
208
+ </section>
209
+ </xsl:template>
210
+
211
+ <xsl:template match="paragraph/*/p | subparagraph/*/p">
212
+ <p>
213
+ <xsl:attribute name="class">
214
+ <xsl:choose>
215
+ <xsl:when test="position() = 1">judgment-body__text judgment-body__no-margin-top</xsl:when>
216
+ <xsl:otherwise>judgment-body__text</xsl:otherwise>
217
+ </xsl:choose>
218
+ </xsl:attribute>
219
+ <xsl:call-template name="inline" />
220
+ </p>
221
+ </xsl:template>
222
+
223
+ <!-- <xsl:template match="hcontainer[@name='tableOfContents']" /> -->
224
+
225
+ <xsl:template match="blockContainer[exists(p)]">
226
+ <xsl:apply-templates select="* except num" />
227
+ </xsl:template>
228
+
229
+ <xsl:template match="blockContainer">
230
+ <xsl:apply-templates />
231
+ </xsl:template>
232
+
233
+ <xsl:template match="blockContainer/num">
234
+ <span style="padding-right:1em">
235
+ <xsl:call-template name="inline" />
236
+ </span>
237
+ </xsl:template>
238
+
239
+ <xsl:template match="blockContainer/p[1]">
240
+ <xsl:param name="class-context" as="element()" tunnel="yes" />
241
+ <p>
242
+ <xsl:if test="exists(ancestor::header)">
243
+ <xsl:variable name="alignment" as="xs:string?" select="uk:extract-alignment(., $class-context)" />
244
+ <xsl:if test="$alignment = ('center', 'right', 'left')">
245
+ <xsl:attribute name="class">
246
+ <xsl:sequence select="concat('judgment-header__pr-', $alignment)" />
247
+ </xsl:attribute>
248
+ </xsl:if>
249
+ </xsl:if>
250
+ <xsl:apply-templates select="../num" />
251
+ <xsl:text> </xsl:text>
252
+ <span>
253
+ <xsl:call-template name="inline" />
254
+ </span>
255
+ </p>
256
+ </xsl:template>
257
+
258
+ <xsl:template match="blockContainer/p[position() gt 1]">
259
+ <xsl:param name="class-context" as="element()" tunnel="yes" />
260
+ <p>
261
+ <xsl:if test="exists(ancestor::header)">
262
+ <xsl:variable name="alignment" as="xs:string?" select="uk:extract-alignment(., $class-context)" />
263
+ <xsl:if test="$alignment = ('center', 'right', 'left')">
264
+ <xsl:attribute name="class">
265
+ <xsl:sequence select="concat('judgment-header__pr-', $alignment)" />
266
+ </xsl:attribute>
267
+ </xsl:if>
268
+ </xsl:if>
269
+ <xsl:call-template name="inline" />
270
+ </p>
271
+ </xsl:template>
272
+
273
+ <!-- quoted structures -->
274
+
275
+ <xsl:template match="block[@name='embeddedStructure']">
276
+ <xsl:apply-templates />
277
+ </xsl:template>
278
+
279
+ <xsl:template match="embeddedStructure">
280
+ <blockquote>
281
+ <xsl:apply-templates />
282
+ </blockquote>
283
+ </xsl:template>
284
+
285
+
286
+ <!-- CSS classes -->
287
+
288
+ <!-- sets the ancestor document element containing the CSS style for its descendants -->
289
+ <!-- if an attachment has its own styles, then that attachment, otherwise the main judgment -->
290
+ <!-- priority should be the highest in the transform -->
291
+ <xsl:template match="akomaNtoso/* | attachment/*[exists(meta/presentation)]" priority="2">
292
+ <xsl:next-match>
293
+ <xsl:with-param name="class-context" select="." tunnel="yes" />
294
+ </xsl:next-match>
295
+ </xsl:template>
296
+
297
+ <!-- a data structure containing all of the CSS properties, divided by selector and property name -->
298
+ <!-- the keys that follow are designed for this structure -->
299
+ <xsl:variable name="all-classes-parsed" as="document-node()">
300
+ <xsl:document>
301
+ <uk:classes>
302
+ <xsl:for-each select="(/akomaNtoso/*, /akomaNtoso/*/attachments/attachment/*)[exists(meta/presentation)]">
303
+ <xsl:variable name="root-key" select="generate-id(.)" />
304
+ <uk:classes key="{ $root-key }">
305
+ <xsl:for-each select="tokenize(string(meta/presentation), '\}')[contains(., '{')]">
306
+ <xsl:variable name="selector" select="normalize-space(substring-before(., '{'))" />
307
+ <xsl:variable name="properties" select="normalize-space(substring-after(., '{'))" />
308
+ <uk:class key="{ $selector }">
309
+ <xsl:for-each select="tokenize($properties, ';')[contains(., ':')]">
310
+ <xsl:variable name="property" select="normalize-space(substring-before(., ':'))" />
311
+ <xsl:variable name="value" select="normalize-space(substring-after(., ':'))" />
312
+ <uk:property key="{ $property }" value="{ $value }" />
313
+ </xsl:for-each>
314
+ </uk:class>
315
+ </xsl:for-each>
316
+ </uk:classes>
317
+ </xsl:for-each>
318
+ </uk:classes>
319
+ </xsl:document>
320
+ </xsl:variable>
321
+
322
+ <xsl:key name="classes" match="uk:class" use="concat(../@key, '|', @key)" />
323
+
324
+ <xsl:key name="class-properties" match="uk:property/@value" use="concat(../../../@key, '|', ../../@key, '|', ../@key)" />
325
+
326
+ <!-- class property getters -->
327
+
328
+ <!-- returns the value of the property for the given selector -->
329
+ <xsl:function name="uk:get-class-property-1" as="xs:string?">
330
+ <xsl:param name="context" as="element()" />
331
+ <xsl:param name="selector" as="xs:string" />
332
+ <xsl:param name="prop" as="xs:string" />
333
+ <xsl:variable name="key" select="concat(generate-id($context), '|', $selector, '|', $prop)" />
334
+ <xsl:sequence select="key('class-properties', $key, $all-classes-parsed)/string()" />
335
+ </xsl:function>
336
+
337
+ <!-- returns a sequence of key/value pairs, each divided by a colon -->
338
+ <xsl:function name="uk:get-all-class-properties" as="xs:string*">
339
+ <xsl:param name="context" as="element()" />
340
+ <xsl:param name="selector" as="xs:string" /> <!-- constructed with 'augment-simple-class-selector' function below -->
341
+ <xsl:variable name="key" select="concat(generate-id($context), '|', $selector)" />
342
+ <xsl:for-each select="key('classes', $key, $all-classes-parsed)/uk:property">
343
+ <xsl:sequence select="concat(@key, ':', @value)" />
344
+ </xsl:for-each>
345
+ </xsl:function>
346
+
347
+ <!-- returns a sequence of key/value pairs, each divided by a colon -->
348
+ <xsl:function name="uk:get-inline-class-properties-1" as="xs:string*">
349
+ <xsl:param name="context" as="element()" />
350
+ <xsl:param name="selector" as="xs:string" /> <!-- constructed with 'make-class-selector' function below -->
351
+ <xsl:variable name="key" select="concat(generate-id($context), '|', $selector)" />
352
+ <xsl:for-each select="key('classes', $key, $all-classes-parsed)/uk:property">
353
+ <xsl:if test="string(@key) = $inline-properties">
354
+ <xsl:sequence select="concat(@key, ':', @value)" />
355
+ </xsl:if>
356
+ </xsl:for-each>
357
+ </xsl:function>
358
+
359
+ <!-- helper functions to make selectors, depending on context -->
360
+
361
+ <!-- adds a prefix to class selector, e.g., #judgment, #main, etc., depending on context -->
362
+ <xsl:function name="uk:augment-simple-class-selector" as="xs:string">
363
+ <xsl:param name="context" as="element()" />
364
+ <xsl:param name="class" as="xs:string" /> <!-- starts with a dot -->
365
+ <xsl:choose>
366
+ <!-- the selector for main styles in a judgment is '#judgment .{ClassName}', e.g., '#judgment .ParaLevel1' -->
367
+ <xsl:when test="$context/self::judgment">
368
+ <xsl:sequence select="concat('#judgment ', $class)" />
369
+ </xsl:when>
370
+ <!-- the selector for main styles in a press summary is '#main .{ClassName}', e.g., '#main .ParaLevel1' -->
371
+ <xsl:when test="$context/self::doc[@name='pressSummary']">
372
+ <xsl:sequence select="concat('#main ', $class)" />
373
+ </xsl:when>
374
+ <!-- the selector for attachment styles is '#{type}{num} .{ClassName}', e.g., '#order1 .ParaLevel1' -->
375
+ <xsl:otherwise>
376
+ <xsl:variable name="work-uri" as="xs:string" select="$context/meta/identification/FRBRWork/FRBRthis/@value" />
377
+ <xsl:variable name="uri-components" as="xs:string*" select="tokenize($work-uri, '/')" />
378
+ <xsl:variable name="last-two" as="xs:string*" select="$uri-components[position() >= last()-1]" />
379
+ <xsl:variable name="last-two-combined" as="xs:string" select="string-join($last-two, '')" />
380
+ <xsl:sequence select="concat('#', $last-two-combined, ' ', $class)" />
381
+ </xsl:otherwise>
382
+ </xsl:choose>
383
+ </xsl:function>
384
+
385
+ <xsl:function name="uk:make-class-selector" as="xs:string?">
386
+ <xsl:param name="context" as="element()" />
387
+ <xsl:param name="e" as="element()" />
388
+ <xsl:choose>
389
+ <xsl:when test="empty($e/@class)" />
390
+ <xsl:when test="$doc-id = 'ewhc/ch/2022/1178'">
391
+ <xsl:sequence select="uk:make-class-selector-for-ewhc-ch-2022-1178($context, $e)" />
392
+ </xsl:when>
393
+ <xsl:otherwise>
394
+ <xsl:sequence select="uk:augment-simple-class-selector($context, concat('.', $e/@class))" />
395
+ </xsl:otherwise>
396
+ </xsl:choose>
397
+ </xsl:function>
398
+
399
+ <!-- [2022] EWHC 1178 (Ch) was generated through a manual process and has some exceptions -->
400
+ <!-- It contains multiple sets of styles -->
401
+ <xsl:function name="uk:make-class-selector-for-ewhc-ch-2022-1178" as="xs:string">
402
+ <xsl:param name="context" as="element()" />
403
+ <xsl:param name="e" as="element()" /> <!-- $e/@class exists -->
404
+ <xsl:variable name="header" as="element()?" select="$e/ancestor::header" />
405
+ <xsl:variable name="decision-id" as="xs:string?" select="$e/ancestor::decision/@eId" />
406
+ <xsl:choose>
407
+ <xsl:when test="$context/self::doc[@name='schedule']">
408
+ <xsl:sequence select="concat('#schedule .', $e/@class)" />
409
+ </xsl:when>
410
+ <xsl:when test="exists($header)">
411
+ <xsl:sequence select="concat('header .', $e/@class, ', #part-a .', $e/@class)" />
412
+ </xsl:when>
413
+ <xsl:when test="exists($decision-id) and $decision-id = 'part-a'"> <!-- same as header -->
414
+ <xsl:sequence select="concat('header .', $e/@class, ', #part-a .', $e/@class)" />
415
+ </xsl:when>
416
+ <xsl:when test="exists($decision-id)">
417
+ <xsl:sequence select="concat('#', $decision-id, ' .', $e/@class)" />
418
+ </xsl:when>
419
+ <xsl:otherwise> <!-- should be impossible -->
420
+ <xsl:sequence select="concat('.', $e/@class)" />
421
+ </xsl:otherwise>
422
+ </xsl:choose>
423
+ </xsl:function>
424
+
425
+ <!-- main class property getters requiring, a source element and a context element -->
426
+
427
+ <xsl:function name="uk:get-class-property" as="xs:string?">
428
+ <xsl:param name="e" as="element()" />
429
+ <xsl:param name="prop" as="xs:string" />
430
+ <xsl:param name="context" as="element()" />
431
+ <xsl:if test="exists($e/@class)">
432
+ <xsl:variable name="selector" as="xs:string" select="uk:make-class-selector($context, $e)" />
433
+ <xsl:sequence select="uk:get-class-property-1($context, $selector, $prop)" />
434
+ </xsl:if>
435
+ </xsl:function>
436
+
437
+ <xsl:function name="uk:get-inline-class-properties" as="xs:string*">
438
+ <xsl:param name="e" as="element()" />
439
+ <xsl:param name="context" as="element()" />
440
+ <xsl:if test="exists($e/@class)">
441
+ <xsl:variable name="selector" as="xs:string" select="uk:make-class-selector($context, $e)" />
442
+ <xsl:sequence select="uk:get-inline-class-properties-1($context, $selector)" />
443
+ </xsl:if>
444
+ </xsl:function>
445
+
446
+ <!-- style property getter -->
447
+
448
+ <xsl:function name="uk:get-style-property" as="xs:string?">
449
+ <xsl:param name="e" as="element()" />
450
+ <xsl:param name="prop" as="xs:string" />
451
+ <xsl:if test="exists($e/@style)">
452
+ <xsl:analyze-string select="$e/@style" regex="{ concat($prop, ' *: *([^;]+)') }">
453
+ <xsl:matching-substring>
454
+ <xsl:sequence select="regex-group(1)"/>
455
+ </xsl:matching-substring>
456
+ </xsl:analyze-string>
457
+ </xsl:if>
458
+ </xsl:function>
459
+
460
+ <xsl:function name="uk:get-style-or-class-property" as="xs:string?">
461
+ <xsl:param name="e" as="element()" />
462
+ <xsl:param name="prop" as="xs:string" />
463
+ <xsl:param name="context" as="element()" />
464
+ <xsl:sequence select="uk:get-style-or-class-property($e, $prop, (), $context)" />
465
+ </xsl:function>
466
+
467
+ <xsl:function name="uk:get-style-or-class-property" as="xs:string?">
468
+ <xsl:param name="e" as="element()" />
469
+ <xsl:param name="prop" as="xs:string" />
470
+ <xsl:param name="default" as="xs:string?" />
471
+ <xsl:param name="context" as="element()" />
472
+ <xsl:variable name="from-style-attribute" as="xs:string?" select="uk:get-style-property($e, $prop)" />
473
+ <xsl:variable name="from-class-attribute" as="xs:string?" select="uk:get-class-property($e, $prop, $context)" />
474
+ <xsl:choose>
475
+ <xsl:when test="exists($from-style-attribute)">
476
+ <xsl:sequence select="$from-style-attribute" />
477
+ </xsl:when>
478
+ <xsl:when test="exists($from-class-attribute)">
479
+ <xsl:sequence select="$from-class-attribute" />
480
+ </xsl:when>
481
+ <xsl:otherwise>
482
+ <xsl:sequence select="$default" />
483
+ </xsl:otherwise>
484
+ </xsl:choose>
485
+ </xsl:function>
486
+
487
+ <xsl:function name="uk:extract-alignment" as="xs:string?">
488
+ <xsl:param name="p" as="element()" />
489
+ <xsl:param name="context" as="element()" />
490
+ <xsl:sequence select="uk:get-style-or-class-property($p, 'text-align', $context)" />
491
+ </xsl:function>
492
+
493
+ <xsl:template match="header//p[not(parent::blockContainer)][not(ancestor::authorialNote)] | coverPage/p">
494
+ <xsl:param name="class-context" as="element()" tunnel="yes" />
495
+ <xsl:choose>
496
+ <xsl:when test="exists(child::img) and (every $block in preceding-sibling::* satisfies $block/@name = 'restriction')">
497
+ <div class="judgment-header__logo">
498
+ <xsl:apply-templates>
499
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
500
+ <xsl:with-param name="is-uppercase" select="uk:is-uppercase(., $class-context)" tunnel="yes" />
501
+ </xsl:apply-templates>
502
+ </div>
503
+ </xsl:when>
504
+ <xsl:when test="exists(child::neutralCitation)">
505
+ <div class="judgment-header__neutral-citation">
506
+ <xsl:apply-templates>
507
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
508
+ <xsl:with-param name="is-uppercase" select="uk:is-uppercase(., $class-context)" tunnel="yes" />
509
+ </xsl:apply-templates>
510
+ </div>
511
+ </xsl:when>
512
+ <xsl:when test="exists(child::docketNumber)">
513
+ <div class="judgment-header__case-number">
514
+ <xsl:apply-templates>
515
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
516
+ <xsl:with-param name="is-uppercase" select="uk:is-uppercase(., $class-context)" tunnel="yes" />
517
+ </xsl:apply-templates>
518
+ </div>
519
+ </xsl:when>
520
+ <xsl:when test="exists(child::courtType)">
521
+ <div class="judgment-header__court">
522
+ <xsl:apply-templates>
523
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
524
+ <xsl:with-param name="is-uppercase" select="uk:is-uppercase(., $class-context)" tunnel="yes" />
525
+ </xsl:apply-templates>
526
+ </div>
527
+ </xsl:when>
528
+ <xsl:when test="exists(child::docDate)">
529
+ <div class="judgment-header__date">
530
+ <xsl:apply-templates>
531
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
532
+ <xsl:with-param name="is-uppercase" select="uk:is-uppercase(., $class-context)" tunnel="yes" />
533
+ </xsl:apply-templates>
534
+ </div>
535
+ </xsl:when>
536
+ <xsl:when test="matches(normalize-space(.), '^- -( -)+$')">
537
+ <div class="judgment-header__line-separator" aria-hidden="true">
538
+ <xsl:apply-templates>
539
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
540
+ <xsl:with-param name="is-uppercase" select="uk:is-uppercase(., $class-context)" tunnel="yes" />
541
+ </xsl:apply-templates>
542
+ </div>
543
+ </xsl:when>
544
+ <xsl:otherwise>
545
+ <xsl:variable name="alignment" as="xs:string?" select="uk:extract-alignment(., $class-context)" />
546
+ <xsl:choose>
547
+ <xsl:when test="$alignment = ('center', 'right', 'left')">
548
+ <p>
549
+ <xsl:attribute name="class">
550
+ <xsl:sequence select="concat('judgment-header__pr-', $alignment)" />
551
+ </xsl:attribute>
552
+ <xsl:call-template name="inline" />
553
+ </p>
554
+ </xsl:when>
555
+ <xsl:otherwise>
556
+ <xsl:next-match />
557
+ </xsl:otherwise>
558
+ </xsl:choose>
559
+ </xsl:otherwise>
560
+ </xsl:choose>
561
+ </xsl:template>
562
+
563
+ <!-- alignment of paragraphs in press summary headers -->
564
+ <xsl:template match="preface/p" priority="1">
565
+ <xsl:param name="class-context" as="element()" tunnel="yes" />
566
+ <xsl:variable name="alignment" as="xs:string?" select="uk:extract-alignment(., $class-context)" />
567
+ <xsl:choose>
568
+ <xsl:when test="$alignment = ('center', 'right', 'left')">
569
+ <p>
570
+ <xsl:attribute name="class">
571
+ <xsl:sequence select="concat('judgment-header__pr-', $alignment)" />
572
+ </xsl:attribute>
573
+ <xsl:call-template name="inline" />
574
+ </p>
575
+ </xsl:when>
576
+ <xsl:otherwise>
577
+ <xsl:next-match />
578
+ </xsl:otherwise>
579
+ </xsl:choose>
580
+ </xsl:template>
581
+
582
+
583
+ <xsl:template match="p">
584
+ <p>
585
+ <xsl:call-template name="inline" />
586
+ </p>
587
+ </xsl:template>
588
+
589
+ <xsl:template match="block">
590
+ <p>
591
+ <xsl:call-template name="inline" />
592
+ </p>
593
+ </xsl:template>
594
+
595
+ <xsl:template match="num | heading">
596
+ <xsl:call-template name="inline" />
597
+ </xsl:template>
598
+
599
+ <xsl:template match="neutralCitation">
600
+ <span class="ncn-nowrap">
601
+ <xsl:call-template name="inline" />
602
+ </span>
603
+ </xsl:template>
604
+
605
+ <xsl:template match="docType | docTitle">
606
+ <xsl:call-template name="inline" />
607
+ </xsl:template>
608
+
609
+ <xsl:template match="courtType | docketNumber | docDate">
610
+ <xsl:call-template name="inline" />
611
+ </xsl:template>
612
+
613
+ <xsl:template match="party | role | judge | lawyer">
614
+ <xsl:call-template name="inline" />
615
+ </xsl:template>
616
+
617
+ <xsl:template match="span">
618
+ <xsl:call-template name="inline" />
619
+ </xsl:template>
620
+
621
+ <!-- all of the inline properties the parser produces -->
622
+ <xsl:variable name="inline-properties" as="xs:string+" select="('font-family', 'font-size', 'font-weight', 'font-style', 'font-variant', 'color', 'background-color', 'text-transform', 'text-decoration-line', 'text-decoration-style', 'vertical-align')" />
623
+
624
+ <xsl:function name="uk:get-combined-inline-styles" as="xs:string*">
625
+ <xsl:param name="e" as="element()" />
626
+ <xsl:param name="context" as="element()" />
627
+ <xsl:variable name="from-class-attr" select="uk:get-inline-class-properties($e, $context)" /><!-- inline formatting implied by the @class -->
628
+ <xsl:variable name="from-style-attr" as="xs:string*"><!-- inline formatting specified in @style -->
629
+ <xsl:for-each select="tokenize($e/@style, ';')">
630
+ <xsl:variable name="prop" as="xs:string" select="normalize-space(substring-before(., ':'))" />
631
+ <xsl:if test="$prop = $inline-properties">
632
+ <xsl:variable name="value" as="xs:string" select="normalize-space(substring-after(., ':'))" />
633
+ <xsl:sequence select="concat($prop, ':', $value)" />
634
+ </xsl:if>
635
+ </xsl:for-each>
636
+ </xsl:variable>
637
+ <xsl:variable name="combined" as="xs:string*"><!-- combined, @style trumps @class -->
638
+ <xsl:variable name="style-properties" as="xs:string*">
639
+ <xsl:for-each select="$from-style-attr">
640
+ <xsl:sequence select="substring-before(., ':')" />
641
+ </xsl:for-each>
642
+ </xsl:variable>
643
+ <xsl:for-each select="$from-class-attr">
644
+ <xsl:variable name="prop" as="xs:string" select="substring-before(., ':')" />
645
+ <xsl:if test="not($prop = $style-properties)">
646
+ <xsl:sequence select="." />
647
+ </xsl:if>
648
+ </xsl:for-each>
649
+ <xsl:sequence select="$from-style-attr" />
650
+ </xsl:variable>
651
+ <!-- remove font, font-size and text-transform -->
652
+ <xsl:for-each select="$combined">
653
+ <xsl:choose>
654
+ <xsl:when test="starts-with(., 'font-family:') and not(contains(., 'Symbol') or contains(., 'Wingdings'))" /> <!-- remove font, except Symbol or Wingdings -->
655
+ <xsl:when test="starts-with(., 'font-size:')" /> <!-- remove font-size -->
656
+ <xsl:when test="starts-with(., 'text-transform:')" /> <!-- remove text-transform -->
657
+ <xsl:when test="starts-with(., 'text-decoration')" /> <!-- remove text-decoration-..., handled by $has-underline -->
658
+ <xsl:otherwise>
659
+ <xsl:sequence select="." />
660
+ </xsl:otherwise>
661
+ </xsl:choose>
662
+ </xsl:for-each>
663
+ </xsl:function>
664
+
665
+ <xsl:template name="inline">
666
+ <xsl:param name="has-underline" as="xs:string*" select="()" tunnel="yes" />
667
+ <xsl:param name="is-uppercase" as="xs:boolean" select="false()" tunnel="yes" />
668
+ <xsl:param name="class-context" as="element()" tunnel="yes" />
669
+ <!-- extract inline styles and recalculate has-underline and is-uppercase -->
670
+ <xsl:variable name="styles" as="xs:string*" select="uk:get-combined-inline-styles(., $class-context)" />
671
+ <xsl:variable name="has-underline" as="xs:string*" select="uk:has-underline(., $has-underline, $class-context)" />
672
+ <xsl:variable name="is-uppercase" as="xs:boolean" select="uk:is-uppercase(., $is-uppercase, $class-context)" />
673
+ <!-- call recursive template -->
674
+ <xsl:call-template name="inline-recursive">
675
+ <xsl:with-param name="styles" select="$styles" />
676
+ <xsl:with-param name="has-underline" select="$has-underline" tunnel="yes" />
677
+ <xsl:with-param name="is-uppercase" select="$is-uppercase" tunnel="yes" />
678
+ </xsl:call-template>
679
+ </xsl:template>
680
+
681
+ <xsl:template name="inline-recursive">
682
+ <xsl:param name="styles" as="xs:string*" />
683
+ <xsl:choose>
684
+ <xsl:when test="exists($styles[starts-with(., 'font-weight:') and not(starts-with(., 'font-weight:normal'))])">
685
+ <b>
686
+ <xsl:if test="exists($styles[starts-with(., 'font-weight:') and not(starts-with(., 'font-weight:bold'))])">
687
+ <xsl:attribute name="style">
688
+ <xsl:value-of select="string-join($styles[starts-with(., 'font-weight:')], ';')" />
689
+ </xsl:attribute>
690
+ </xsl:if>
691
+ <xsl:call-template name="inline-recursive">
692
+ <xsl:with-param name="styles" select="$styles[not(starts-with(., 'font-weight:'))]" />
693
+ </xsl:call-template>
694
+ </b>
695
+ </xsl:when>
696
+ <xsl:when test="exists($styles[starts-with(., 'font-style:') and not(starts-with(., 'font-style:normal'))])">
697
+ <i>
698
+ <xsl:if test="exists($styles[starts-with(., 'font-style:') and not(starts-with(., 'font-style:italic'))])">
699
+ <xsl:attribute name="style">
700
+ <xsl:value-of select="string-join($styles[starts-with(., 'font-style:')], ';')" />
701
+ </xsl:attribute>
702
+ </xsl:if>
703
+ <xsl:call-template name="inline-recursive">
704
+ <xsl:with-param name="styles" select="$styles[not(starts-with(., 'font-style:'))]" />
705
+ </xsl:call-template>
706
+ </i>
707
+ </xsl:when>
708
+ <xsl:when test="exists($styles[. = 'vertical-align:super'])">
709
+ <sup>
710
+ <xsl:call-template name="inline-recursive">
711
+ <xsl:with-param name="styles" select="$styles[not(starts-with(., 'vertical-align:'))]" />
712
+ </xsl:call-template>
713
+ </sup>
714
+ </xsl:when>
715
+ <xsl:when test="exists($styles[. = 'vertical-align:sub'])">
716
+ <sub>
717
+ <xsl:call-template name="inline-recursive">
718
+ <xsl:with-param name="styles" select="$styles[not(starts-with(., 'vertical-align:'))]" />
719
+ </xsl:call-template>
720
+ </sub>
721
+ </xsl:when>
722
+ <xsl:when test="exists($styles)">
723
+ <span>
724
+ <xsl:attribute name="style">
725
+ <xsl:value-of select="string-join($styles, ';')" />
726
+ </xsl:attribute>
727
+ <xsl:apply-templates />
728
+ </span>
729
+ </xsl:when>
730
+ <xsl:otherwise>
731
+ <xsl:apply-templates />
732
+ </xsl:otherwise>
733
+ </xsl:choose>
734
+ </xsl:template>
735
+
736
+ <xsl:template match="img">
737
+ <img>
738
+ <xsl:apply-templates select="@*" />
739
+ <xsl:apply-templates />
740
+ </img>
741
+ </xsl:template>
742
+ <xsl:template match="img/@src">
743
+ <xsl:attribute name="src">
744
+ <xsl:sequence select="concat($image-base, $doc-id, '/', .)" />
745
+ </xsl:attribute>
746
+ </xsl:template>
747
+
748
+ <xsl:template match="img/@style">
749
+ <xsl:next-match>
750
+ <xsl:with-param name="properties" select="('width', 'height')" />
751
+ </xsl:next-match>
752
+ </xsl:template>
753
+
754
+ <xsl:template match="br">
755
+ <br />
756
+ </xsl:template>
757
+
758
+ <xsl:template match="date">
759
+ <xsl:call-template name="inline" />
760
+ </xsl:template>
761
+
762
+
763
+ <!-- tables -->
764
+
765
+ <xsl:template match="table">
766
+ <div class="judgment-body__table">
767
+ <table>
768
+ <xsl:variable name="header-rows" as="element()*" select="*[child::th]" />
769
+ <xsl:if test="exists($header-rows)">
770
+ <thead>
771
+ <xsl:apply-templates select="$header-rows">
772
+ <xsl:with-param name="table-class" as="xs:string?" select="@class" tunnel="yes" />
773
+ </xsl:apply-templates>
774
+ </thead>
775
+ </xsl:if>
776
+ <tbody>
777
+ <xsl:apply-templates select="* except $header-rows">
778
+ <xsl:with-param name="table-class" as="xs:string?" select="@class" tunnel="yes" />
779
+ </xsl:apply-templates>
780
+ </tbody>
781
+ </table>
782
+ </div>
783
+ </xsl:template>
784
+
785
+ <xsl:template match="tr | th | td">
786
+ <xsl:param name="class-context" as="element()" tunnel="yes" />
787
+ <xsl:param name="table-class" as="xs:string?" tunnel="yes" />
788
+ <xsl:element name="{ local-name() }">
789
+ <xsl:copy-of select="@*" />
790
+ <xsl:if test="$table-class">
791
+ <xsl:variable name="selector" as="xs:string" select="concat('.', $table-class, ' ', local-name(.))" /> <!-- e.g., '.TableClass1 td' -->
792
+ <xsl:variable name="selector" as="xs:string" select="uk:augment-simple-class-selector($class-context, $selector)" /> <!-- e.g., '#judgment .TableClass1 td' -->
793
+ <xsl:variable name="table-class-properties" select="uk:get-all-class-properties($class-context, $selector)" />
794
+ <xsl:if test="exists($table-class-properties)">
795
+ <xsl:attribute name="style">
796
+ <xsl:value-of select="string-join($table-class-properties, ';')" />
797
+ <xsl:if test="exists(@style)">
798
+ <xsl:value-of select="';'" />
799
+ <xsl:value-of select="concat(';', @style)" />
800
+ </xsl:if>
801
+ </xsl:attribute>
802
+ </xsl:if>
803
+ </xsl:if>
804
+ <xsl:apply-templates />
805
+ </xsl:element>
806
+ </xsl:template>
807
+
808
+ <!-- header tables -->
809
+
810
+ <xsl:template match="header//table">
811
+ <xsl:choose>
812
+ <xsl:when test="every $row in * satisfies uk:can-remove-first-column($row)">
813
+ <xsl:apply-templates select="." mode="remove-first-column" />
814
+ </xsl:when>
815
+ <xsl:otherwise>
816
+ <xsl:next-match />
817
+ </xsl:otherwise>
818
+ </xsl:choose>
819
+ </xsl:template>
820
+
821
+ <xsl:function name="uk:can-remove-first-column" as="xs:boolean">
822
+ <xsl:param name="row" as="element()" />
823
+ <xsl:sequence select="count($row/*) = 3 and uk:cell-is-empty($row/*[1])" />
824
+ </xsl:function>
825
+
826
+ <xsl:function name="uk:cell-is-empty" as="xs:boolean">
827
+ <xsl:param name="cell" as="element()" />
828
+ <xsl:sequence select="uk:cell-span-is-effectively-one($cell/@colspan) and uk:cell-span-is-effectively-one($cell/@rowspan) and not(normalize-space(string($cell)))" />
829
+ </xsl:function>
830
+
831
+ <xsl:function name="uk:cell-span-is-effectively-one" as="xs:boolean">
832
+ <xsl:param name="attr" as="attribute()?" />
833
+ <xsl:sequence select="empty($attr) or string($attr) = '' or string($attr) = '1'" />
834
+ </xsl:function>
835
+
836
+ <xsl:template match="table" mode="remove-first-column">
837
+ <table class="pr-two-column">
838
+ <tbody>
839
+ <xsl:apply-templates mode="remove-first-column" />
840
+ </tbody>
841
+ </table>
842
+ </xsl:template>
843
+
844
+ <xsl:template match="tr" mode="remove-first-column">
845
+ <tr>
846
+ <xsl:apply-templates select="*[position() gt 1]" mode="remove-first-column" />
847
+ </tr>
848
+ </xsl:template>
849
+
850
+ <xsl:template match="th | td" mode="remove-first-column">
851
+ <xsl:element name="{ local-name() }">
852
+ <xsl:apply-templates />
853
+ </xsl:element>
854
+ </xsl:template>
855
+
856
+
857
+ <!-- links -->
858
+
859
+ <xsl:template match="a | ref">
860
+ <xsl:choose>
861
+ <xsl:when test="uk:link-is-supported(@href)">
862
+ <a>
863
+ <xsl:apply-templates select="@href" />
864
+ <xsl:call-template name="inline" />
865
+ </a>
866
+ </xsl:when>
867
+ <xsl:otherwise>
868
+ <xsl:call-template name="inline" />
869
+ </xsl:otherwise>
870
+ </xsl:choose>
871
+ </xsl:template>
872
+
873
+
874
+ <!-- tables of contents -->
875
+
876
+ <xsl:template match="toc">
877
+ <div>
878
+ <xsl:apply-templates />
879
+ </div>
880
+ </xsl:template>
881
+
882
+ <xsl:template match="tocItem">
883
+ <p>
884
+ <xsl:call-template name="inline" />
885
+ </p>
886
+ </xsl:template>
887
+
888
+
889
+ <!-- markers and attributes -->
890
+
891
+ <xsl:template match="marker[@name='tab']">
892
+ <span>
893
+ <xsl:text> </xsl:text>
894
+ </span>
895
+ </xsl:template>
896
+
897
+ <xsl:template match="@style">
898
+ <xsl:param name="properties" as="xs:string*" select="('font-weight', 'font-style', 'text-transform', 'font-variant', 'text-decoration-line', 'text-decoration-style')" />
899
+ <xsl:variable name="values" as="xs:string*">
900
+ <xsl:for-each select="tokenize(., ';')">
901
+ <xsl:if test="tokenize(., ':')[1] = $properties">
902
+ <xsl:sequence select="." />
903
+ </xsl:if>
904
+ </xsl:for-each>
905
+ </xsl:variable>
906
+ <xsl:if test="exists($values)">
907
+ <xsl:attribute name="style">
908
+ <xsl:sequence select="string-join($values, ';')" />
909
+ </xsl:attribute>
910
+ </xsl:if>
911
+ </xsl:template>
912
+
913
+ <xsl:template match="@src | @href | @title">
914
+ <xsl:copy />
915
+ </xsl:template>
916
+
917
+ <xsl:template match="@class | @refersTo | @date | @as" />
918
+
919
+ <xsl:template match="@*" />
920
+
921
+
922
+ <!-- footnotes -->
923
+
924
+ <xsl:template match="authorialNote">
925
+ <xsl:variable name="marker" as="xs:string" select="@marker" />
926
+ <a id="{ concat('fnref', $marker) }" href="{ concat('#fn', $marker) }" class="judgment-body__footnote-reference">
927
+ <span class="judgment__hidden"> (Footnote: </span>
928
+ <sup>
929
+ <xsl:value-of select="$marker" />
930
+ </sup>
931
+ <span class="judgment__hidden">)</span>
932
+ </a>
933
+ </xsl:template>
934
+
935
+ <xsl:template name="footnotes">
936
+ <xsl:param name="footnotes" as="element()*" select="descendant::authorialNote" />
937
+ <xsl:if test="exists($footnotes)">
938
+ <footer class="judgment-footer">
939
+ <hr />
940
+ <xsl:apply-templates select="$footnotes" mode="footnote" />
941
+ </footer>
942
+ </xsl:if>
943
+ </xsl:template>
944
+
945
+ <xsl:template match="authorialNote" mode="footnote">
946
+ <div>
947
+ <xsl:apply-templates />
948
+ </div>
949
+ </xsl:template>
950
+
951
+ <xsl:template match="authorialNote/p[1]">
952
+ <xsl:variable name="marker" as="xs:string" select="../@marker" />
953
+ <p id="{ concat('fn', $marker) }" class="judgment-footer__footnote">
954
+ <a href="{ concat('#fnref', $marker) }" class="judgment-footer__footnote-backlink">
955
+ <span class="judgment__hidden"> (Footnote reference from: </span>
956
+ <sup>
957
+ <xsl:value-of select="$marker" />
958
+ </sup>
959
+ <span class="judgment__hidden">)</span>
960
+ </a>
961
+ <xsl:text> </xsl:text>
962
+ <xsl:call-template name="inline" />
963
+ </p>
964
+ </xsl:template>
965
+
966
+
967
+ <!-- math -->
968
+
969
+ <xsl:template match="math:*">
970
+ <xsl:element name="{ local-name(.) }">
971
+ <xsl:copy-of select="@*"/>
972
+ <xsl:apply-templates />
973
+ </xsl:element>
974
+ </xsl:template>
975
+
976
+
977
+ <!-- text -->
978
+
979
+ <xsl:function name="uk:is-uppercase" as="xs:boolean">
980
+ <xsl:param name="p" as="element()" />
981
+ <xsl:param name="context" as="element()" />
982
+ <xsl:sequence select="uk:is-uppercase($p, false(), $context)" />
983
+ </xsl:function>
984
+
985
+ <xsl:function name="uk:is-uppercase" as="xs:boolean">
986
+ <xsl:param name="e" as="element()" />
987
+ <xsl:param name="default" as="xs:boolean" />
988
+ <xsl:param name="context" as="element()" />
989
+ <xsl:variable name="text-transform" as="xs:string?" select="uk:get-style-or-class-property($e, 'text-transform', $context)" />
990
+ <xsl:choose>
991
+ <xsl:when test="exists($text-transform)">
992
+ <xsl:sequence select="$text-transform = 'uppercase'" />
993
+ </xsl:when>
994
+ <xsl:otherwise>
995
+ <xsl:sequence select="$default" />
996
+ </xsl:otherwise>
997
+ </xsl:choose>
998
+ </xsl:function>
999
+
1000
+ <!-- the following two functions return a sequence of 0, 1 or 2 values:
1001
+ the first is for the text-decoration-line property,
1002
+ the second is for the text-decoration-style property -->
1003
+
1004
+ <xsl:function name="uk:has-underline" as="xs:string*">
1005
+ <xsl:param name="p" as="element()" />
1006
+ <xsl:param name="context" as="element()" />
1007
+ <xsl:sequence select="uk:has-underline($p, (), $context)" />
1008
+ </xsl:function>
1009
+
1010
+ <xsl:function name="uk:has-underline" as="xs:string*">
1011
+ <xsl:param name="e" as="element()" />
1012
+ <xsl:param name="default" as="xs:string*" />
1013
+ <xsl:param name="context" as="element()" />
1014
+ <xsl:variable name="decor-line" as="xs:string?" select="uk:get-style-or-class-property($e, 'text-decoration-line', $default[1], $context)" />
1015
+ <xsl:variable name="decor-style" as="xs:string?" select="uk:get-style-or-class-property($e, 'text-decoration-style', $default[2], $context)" />
1016
+ <xsl:sequence select="$decor-line" />
1017
+ <xsl:if test="exists($decor-line)">
1018
+ <xsl:sequence select="$decor-style" />
1019
+ </xsl:if>
1020
+ </xsl:function>
1021
+
1022
+ <xsl:template match="text()">
1023
+ <xsl:param name="has-underline" as="xs:string*" select="()" tunnel="yes" />
1024
+ <xsl:param name="is-uppercase" as="xs:boolean" select="false()" tunnel="yes" />
1025
+ <xsl:choose>
1026
+ <xsl:when test="exists($has-underline) and $has-underline[1] = 'none'">
1027
+ <xsl:next-match>
1028
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
1029
+ </xsl:next-match>
1030
+ </xsl:when>
1031
+ <xsl:when test="exists($has-underline)">
1032
+ <xsl:variable name="decor-line" as="xs:string" select="$has-underline[1]" />
1033
+ <xsl:variable name="decor-style" as="xs:string?" select="$has-underline[2]" />
1034
+ <xsl:variable name="styles" as="xs:string*">
1035
+ <xsl:if test="$decor-line != 'underline'">
1036
+ <xsl:sequence select="concat('text-decoration-line:', $decor-line)" />
1037
+ </xsl:if>
1038
+ <xsl:if test="exists($decor-style) and $decor-style != 'solid'">
1039
+ <xsl:sequence select="concat('text-decoration-style:', $decor-style)" />
1040
+ </xsl:if>
1041
+ </xsl:variable>
1042
+ <u>
1043
+ <xsl:if test="exists($styles)">
1044
+ <xsl:attribute name="style">
1045
+ <xsl:sequence select="string-join($styles, ';')" />
1046
+ </xsl:attribute>
1047
+ </xsl:if>
1048
+ <xsl:next-match>
1049
+ <xsl:with-param name="has-underline" select="()" tunnel="yes" />
1050
+ </xsl:next-match>
1051
+ </u>
1052
+ </xsl:when>
1053
+ <xsl:when test="$is-uppercase">
1054
+ <xsl:value-of select="upper-case(.)" />
1055
+ </xsl:when>
1056
+ <xsl:otherwise>
1057
+ <xsl:copy />
1058
+ </xsl:otherwise>
1059
+ </xsl:choose>
1060
+ </xsl:template>
1061
+
1062
+ </xsl:transform>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ds-caselaw-marklogic-api-client
3
- Version: 27.0.1
3
+ Version: 27.1.0
4
4
  Summary: An API client for interacting with the underlying data in Find Caselaw.
5
5
  Home-page: https://github.com/nationalarchives/ds-caselaw-custom-api-client
6
6
  Keywords: national archives,caselaw
@@ -24,6 +24,7 @@ Requires-Dist: python-dateutil (>=2.9.0-post.0,<3.0.0)
24
24
  Requires-Dist: pytz (>=2024.1,<2025.0)
25
25
  Requires-Dist: requests (>=2.28.2,<3.0.0)
26
26
  Requires-Dist: requests-toolbelt (>=0.10.1,<1.1.0)
27
+ Requires-Dist: saxonche (>=12.5.0,<13.0.0)
27
28
  Requires-Dist: typing-extensions (>=4.7.1,<5.0.0)
28
29
  Description-Content-Type: text/markdown
29
30
 
@@ -1,15 +1,16 @@
1
- caselawclient/Client.py,sha256=9tNNo_-qNxIn5E3OUJLg3apVvUie8VfyRfPmnzeqc-0,40182
1
+ caselawclient/Client.py,sha256=CP7wx_Z_RKK6Wg4Ib3JypEXbncL1jNsLmo66MyXxcF0,40295
2
2
  caselawclient/__init__.py,sha256=DY-caubLDQWWingSdsBWgovDNXh8KcnkI6kwz08eIFk,612
3
3
  caselawclient/client_helpers/__init__.py,sha256=fyDNKCdrTb2N0Ks23YDhmvlXKfLTHnYQCXhnZb-QQbg,3832
4
4
  caselawclient/client_helpers/search_helpers.py,sha256=R99HyRLeYHgsw2L3DOidEqlKLLvs6Tga5rKTuWQViig,1525
5
5
  caselawclient/content_hash.py,sha256=0cPC4OoABq0SC2wYFX9-24DodNigeOqksDxgxQH_hUA,2221
6
6
  caselawclient/errors.py,sha256=tV0vs3wYSd331BzmfuRiZV6GAdsd91rtN65ymRaSx3s,3164
7
- caselawclient/factories.py,sha256=WkymzhT2Hh9RwJUh2OjjgI110Td4eDzWKFdNVATImCQ,5197
7
+ caselawclient/factories.py,sha256=wTGGP8VyUME2gwbnuYE2uC5PdCdJ2PXF9gEET3U9CZg,4356
8
8
  caselawclient/models/__init__.py,sha256=kd23EUpvaC7aLHdgk8farqKAQEx3lf7RvNT2jEatvlg,68
9
- caselawclient/models/documents/__init__.py,sha256=EwfkYMr5HnmdtxijKwU6AV27Y4JAmobdNHL9Cp--bBs,16624
10
- caselawclient/models/documents/body.py,sha256=0o8qL7oJ40VikNAgqS41phQyB8Jtfz93eK1KyR4k3F0,4791
9
+ caselawclient/models/documents/__init__.py,sha256=LnAURUtxoY4UdDUk-dFgnyJ-Gn9eB0VfdC4gjNoYacM,16974
10
+ caselawclient/models/documents/body.py,sha256=mtdjmG1WU2qSpyRLS8-PWcSoXpDa2Qz6xlcTbxZgxvA,5603
11
11
  caselawclient/models/documents/exceptions.py,sha256=Mz1P8uNqf5w6uLnRwJt6xK7efsVqtd5VA-WXUUH7QLk,285
12
12
  caselawclient/models/documents/statuses.py,sha256=Cp4dTQmJOtsU41EJcxy5dV1841pGD2PNWH0VrkDEv4Q,579
13
+ caselawclient/models/documents/transforms/html.xsl,sha256=BTo3dsjJywmw28rnPB-AwRXZk8hY8Bi7KqEkg8tsOuQ,38131
13
14
  caselawclient/models/documents/xml.py,sha256=afEsgcnTThqW_gKYq-VGtFr4ovOoT2J7h2gXX7F8BbE,1267
14
15
  caselawclient/models/judgments.py,sha256=SuCNtOD4LElp37df4dvhaD0umTowioWH0sZNmBgFsoE,1739
15
16
  caselawclient/models/neutral_citation_mixin.py,sha256=5ktKCPIDidVRwxVTzx5e242O1BxOdP--1dnatZyTbYI,1773
@@ -65,7 +66,7 @@ caselawclient/xquery/validate_document.xqy,sha256=PgaDcnqCRJPIVqfmWsNlXmCLNKd21q
65
66
  caselawclient/xquery/xslt.xqy,sha256=w57wNijH3dkwHkpKeAxqjlghVflQwo8cq6jS_sm-erM,199
66
67
  caselawclient/xquery/xslt_transform.xqy,sha256=smyFFxqmtkuOzBd2l7uw6K2oAsYctudrP8omdv_XNAM,2463
67
68
  caselawclient/xquery_type_dicts.py,sha256=YOrXbEYJU84S-YwergCI12OL5Wrn_wpqMcqWpsQrKek,5590
68
- ds_caselaw_marklogic_api_client-27.0.1.dist-info/LICENSE.md,sha256=fGMzyyLuQW-IAXUeDSCrRdsYW536aEWThdbpCjo6ZKg,1108
69
- ds_caselaw_marklogic_api_client-27.0.1.dist-info/METADATA,sha256=gN0HbwNyMc1ZTW2zYZYjA2q9E7-qkqrjDKQaDvqbBB0,4189
70
- ds_caselaw_marklogic_api_client-27.0.1.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
71
- ds_caselaw_marklogic_api_client-27.0.1.dist-info/RECORD,,
69
+ ds_caselaw_marklogic_api_client-27.1.0.dist-info/LICENSE.md,sha256=fGMzyyLuQW-IAXUeDSCrRdsYW536aEWThdbpCjo6ZKg,1108
70
+ ds_caselaw_marklogic_api_client-27.1.0.dist-info/METADATA,sha256=gYAgOwD-FrETnEArRn9NSyZ2Yl2EvBOFPse-fWZNI7w,4232
71
+ ds_caselaw_marklogic_api_client-27.1.0.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
72
+ ds_caselaw_marklogic_api_client-27.1.0.dist-info/RECORD,,