Skip to content

Commit 89e5444

Browse files
committed
[refactor] New implementation of TEI to Markdown, and Markdown to TEI conversions using XSLT
1 parent de0959f commit 89e5444

9 files changed

Lines changed: 7192 additions & 1 deletion

File tree

pom.xml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@
5454
<public.xar.repo.uri>https://exist-db.org/exist/apps/public-repo</public.xar.repo.uri>
5555

5656
<!-- NOTE(AR): this is used for generating forms in the xml-maven-plugin below -->
57-
<saxon.version>9.9.1-8</saxon.version>
57+
<saxon.version>12.9</saxon.version>
58+
59+
<xspec.version>3.1.3</xspec.version>
5860

5961
<!-- used in the EXPath Package Descriptor -->
6062
<package-title>${project.name}</package-title>
@@ -214,6 +216,35 @@
214216
</execution>
215217
</executions>
216218
</plugin>
219+
<plugin>
220+
<groupId>io.xspec.maven</groupId>
221+
<artifactId>xspec-maven-plugin</artifactId>
222+
<version>${xspec.version}</version>
223+
<executions>
224+
<execution>
225+
<id>services-xspec-tests</id>
226+
<phase>test</phase>
227+
<goals>
228+
<goal>run-xspec</goal>
229+
</goals>
230+
<configuration>
231+
<testDir>src/test/xar-resources</testDir>
232+
</configuration>
233+
</execution>
234+
</executions>
235+
<dependencies>
236+
<dependency>
237+
<groupId>io.xspec</groupId>
238+
<artifactId>xspec</artifactId>
239+
<version>${xspec.version}</version>
240+
</dependency>
241+
<dependency>
242+
<groupId>net.sf.saxon</groupId>
243+
<artifactId>Saxon-HE</artifactId>
244+
<version>${saxon.version}</version>
245+
</dependency>
246+
</dependencies>
247+
</plugin>
217248
<plugin>
218249
<groupId>ro.kuberam.maven.plugins</groupId>
219250
<artifactId>kuberam-expath-plugin</artifactId>
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet
3+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4+
xmlns:xs="http://www.w3.org/2001/XMLSchema"
5+
xmlns:tei="http://www.tei-c.org/ns/1.0"
6+
xmlns:m2t="http://manuforma-form-to-tei"
7+
exclude-result-prefixes="xs"
8+
version="2.0">
9+
10+
<!--
11+
Convert TEI like submission from a manuForma form to TEI
12+
@author Adam Retter
13+
-->
14+
15+
<xsl:param name="new" as="xs:boolean" select="false()"/>
16+
<xsl:param name="id" as="xs:string" required="yes"/>
17+
<xsl:param name="uri" as="xs:string?" required="yes"/>
18+
<xsl:param name="user-id" as="xs:string" select="'guest'"/>
19+
<xsl:param name="user-name" as="xs:string" select="'Guest'"/>
20+
21+
22+
<xsl:import href="markdown-to-tei.xslt"/>
23+
24+
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" encoding="UTF-8" indent="yes"/>
25+
26+
27+
<xsl:template match="tei:TEI">
28+
<xsl:copy>
29+
<xsl:apply-templates select="node()|@*[local-name() ne 'class']"/>
30+
</xsl:copy>
31+
</xsl:template>
32+
33+
<!-- Elements that match this template are Markdown containers -->
34+
<xsl:template match="tei:note|tei:summary[not(parent::tei:layoutDesc)]|tei:quote">
35+
<xsl:copy>
36+
<xsl:apply-templates select="@*"/>
37+
<xsl:for-each select="node()">
38+
<xsl:choose>
39+
<xsl:when test=". instance of text()">
40+
<xsl:apply-templates select="." mode="markdown-to-tei-container"/>
41+
</xsl:when>
42+
<xsl:otherwise>
43+
<xsl:apply-templates select="." mode="markdown-to-tei"/>
44+
</xsl:otherwise>
45+
</xsl:choose>
46+
</xsl:for-each>
47+
</xsl:copy>
48+
</xsl:template>
49+
50+
<xsl:template match="tei:ab[@type eq 'factoid'][@subtype eq 'relation']">
51+
<xsl:call-template name="copy-with-updated-id-and-source">
52+
<xsl:with-param name="id" select="concat('factoid-', $id)"/>
53+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
54+
</xsl:call-template>
55+
</xsl:template>
56+
57+
<!-- Add a Contributor into the titleStmt Element -->
58+
<xsl:template match="tei:titleStmt">
59+
<xsl:copy>
60+
<xsl:apply-templates select="@*"/>
61+
<xsl:apply-templates select="tei:title,tei:author,tei:sponsor,tei:funder,tei:principal"/>
62+
<xsl:apply-templates select="tei:editor[exists((text(), @ref)[normalize-space(.) ne ''])]"/>
63+
<xsl:if test="$user-id ne 'guest' and empty(tei:editor[. eq $user-name])">
64+
<tei:editor xml:id="{$user-id}" role="contributor"><xsl:value-of select="$user-name"/></tei:editor>
65+
</xsl:if>
66+
<xsl:apply-templates select="tei:meeting,tei:respStmt"/>
67+
</xsl:copy>
68+
</xsl:template>
69+
70+
<xsl:template match="tei:idno[parent::tei:ab[@type eq 'factoid'][@subtype eq 'relation']]">
71+
<xsl:call-template name="copy-with-updated-id-and-source">
72+
<xsl:with-param name="id" select="concat('name-', count(preceding-sibling::tei:idno) + 1)"/>
73+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
74+
</xsl:call-template>
75+
</xsl:template>
76+
77+
<xsl:template match="tei:idno[parent::tei:publicationStmt]">
78+
<xsl:copy>
79+
<xsl:apply-templates select="node()|@*"/>
80+
<xsl:if test="$new">
81+
<xsl:value-of select="$uri"/>
82+
</xsl:if>
83+
</xsl:copy>
84+
</xsl:template>
85+
86+
<xsl:template match="tei:place[parent::tei:listPlace]">
87+
<xsl:call-template name="copy-with-updated-id-and-source">
88+
<xsl:with-param name="id" select="concat('place-', $id)"/>
89+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
90+
</xsl:call-template>
91+
</xsl:template>
92+
93+
<xsl:template match="tei:placeName[parent::tei:place/parent::tei:listPlace]">
94+
<xsl:call-template name="copy-with-updated-id-and-source">
95+
<xsl:with-param name="id" select="concat('name-', count(preceding-sibling::tei:placeName) + 1)"/>
96+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
97+
</xsl:call-template>
98+
</xsl:template>
99+
100+
<xsl:template match="tei:bibl[parent::tei:place/parent::tei:listPlace or parent::tei:person/parent::tei:listPerson or parent::tei:bibl/parent::tei:bibl/parent::tei:body]">
101+
<xsl:copy>
102+
<xsl:apply-templates select="@*[name(.) ne 'source']"/>
103+
<!-- xsl:attribute name="xml:id" select="concat('bibl-', count(preceding-sibling::tei:bibl) + 1)"/ -->
104+
<xsl:apply-templates select="node()"/>
105+
</xsl:copy>
106+
</xsl:template>
107+
108+
<xsl:template match="tei:bibl[parent::tei:body/parent::tei:text]">
109+
<xsl:copy>
110+
<xsl:apply-templates select="@*[name(.) ne 'source']"/>
111+
<!-- xsl:attribute name="xml:id" select="concat('work-', $id)"/ -->
112+
<xsl:apply-templates select="node()"/>
113+
</xsl:copy>
114+
</xsl:template>
115+
116+
<xsl:template match="tei:bibl[parent::tei:listBibl/parent::tei:additional/parent::tei:msDesc]">
117+
<xsl:copy>
118+
<xsl:apply-templates select="@*[name(.) ne 'source']"/>
119+
<!-- xsl:attribute name="xml:id" select="concat('bibl-', (count(parent::tei:listBibl/parent::tei:additional/preceding-sibling::tei:additional) + 1), '.', (count(parent::tei:listBibl/preceding-sibling::tei:listBibl) + 1), '.', (count(preceding-sibling::tei:bibl) + 1))"/ -->
120+
<xsl:apply-templates select="node()"/>
121+
</xsl:copy>
122+
</xsl:template>
123+
124+
<xsl:template match="tei:title[parent::tei:bibl/parent::tei:body]">
125+
<xsl:call-template name="copy-with-updated-id-and-source">
126+
<xsl:with-param name="id" select="concat('title-', count(preceding-sibling::tei:title) + 1)"/>
127+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
128+
</xsl:call-template>
129+
</xsl:template>
130+
131+
<!-- Drop empty title elements -->
132+
<xsl:template match="tei:title[empty((text(), @ref)[normalize-space(.) ne ''])]" priority="2"/>
133+
134+
<xsl:template match="tei:person[parent::tei:listPerson]">
135+
<xsl:call-template name="copy-with-updated-id-and-source">
136+
<xsl:with-param name="id" select="concat('person-', $id)"/>
137+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
138+
</xsl:call-template>
139+
</xsl:template>
140+
141+
<xsl:template match="tei:persName[parent::tei:person/parent::tei:listPerson]">
142+
<xsl:call-template name="copy-with-updated-id-and-source">
143+
<xsl:with-param name="id" select="concat('name-', count(preceding-sibling::tei:persName) + 1)"/>
144+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
145+
</xsl:call-template>
146+
</xsl:template>
147+
148+
<xsl:template match="tei:msDesc[parent::tei:person/parent::tei:listPerson]">
149+
<xsl:call-template name="copy-with-updated-id-and-source">
150+
<xsl:with-param name="id" select="concat('ms-', $id)"/>
151+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
152+
</xsl:call-template>
153+
</xsl:template>
154+
155+
<xsl:template match="tei:msItem[parent::tei:msContents/parent::tei:msDesc]">
156+
<xsl:call-template name="copy-with-updated-id-and-source">
157+
<xsl:with-param name="id" select="concat('item-', (count(parent::tei:msContents/preceding-sibling::tei:msContents) + 1), '.', (count(preceding-sibling::tei:msItem) + 1))"/>
158+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
159+
</xsl:call-template>
160+
</xsl:template>
161+
162+
<xsl:template match="tei:layout[parent::tei:layoutDesc/parent::tei:objectDesc/parent::tei:physDesc/parent::tei:msDesc]">
163+
<xsl:call-template name="copy-with-updated-id-and-source">
164+
<xsl:with-param name="id" select="concat('layout-', (count(parent::tei:layoutDesc/parent::tei:objectDesc/parent::tei:physDesc/preceding-sibling::tei:physDesc) + 1), '.', (count(parent::tei:layoutDesc/parent::tei:objectDesc/preceding-sibling::tei:objectDesc) + 1), '.', (count(parent::tei:layoutDesc/preceding-sibling::tei:layoutDesc) + 1), '.', (count(preceding-sibling::tei:layout) + 1))"/>
165+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
166+
</xsl:call-template>
167+
</xsl:template>
168+
169+
<xsl:template match="tei:handNote[parent::tei:handDesc/parent::tei:physDesc/parent::tei:msDesc]">
170+
<xsl:call-template name="copy-with-updated-id-and-source">
171+
<xsl:with-param name="id" select="concat('hand-', (count(parent::tei:handDesc/parent::tei:physDesc/preceding-sibling::tei:physDesc) + 1), '.', (count(parent::tei:handDesc/preceding-sibling::tei:handDesc) + 1), '.', (count(preceding-sibling::tei:handNote) + 1))"/>
172+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
173+
</xsl:call-template>
174+
</xsl:template>
175+
176+
<xsl:template match="tei:item[parent::tei:list/parent::tei:additions/parent::tei:physDesc/parent::tei:msDesc]">
177+
<xsl:call-template name="copy-with-updated-id-and-source">
178+
<xsl:with-param name="id" select="concat('add-', (count(parent::tei:list/parent::tei:additions/parent::tei:physDesc/preceding-sibling::tei:physDesc) + 1), '.', (count(parent::tei:list/parent::tei:additions/preceding-sibling::tei:additions) + 1), '.', (count(parent::tei:list/preceding-sibling::tei:list) + 1), '.', (count(preceding-sibling::tei:item) + 1))"/>
179+
<xsl:with-param name="source" select="m2t:extract-source(@source)"/>
180+
</xsl:call-template>
181+
</xsl:template>
182+
183+
<xsl:template match="tei:relation[exists((tei:active, tei:mutual, tei:passive))]">
184+
<xsl:copy>
185+
<xsl:apply-templates select="@*[not(name(.) = ('active', 'mutual', 'passive'))]"/>
186+
<xsl:if test="tei:active/@ref">
187+
<xsl:attribute name="active" select="string-join(tei:active/@ref, ' ')"/>
188+
</xsl:if>
189+
<xsl:if test="tei:mutual/@ref">
190+
<xsl:attribute name="mutual" select="string-join(tei:mutual/@ref, ' ')"/>
191+
</xsl:if>
192+
<xsl:if test="tei:passive/@ref">
193+
<xsl:attribute name="passive" select="string-join(tei:passive/@ref, ' ')"/>
194+
</xsl:if>
195+
</xsl:copy>
196+
</xsl:template>
197+
198+
<xsl:function name="m2t:extract-source" as="xs:string">
199+
<xsl:param name="input" as="xs:string" required="yes"/>
200+
<xsl:sequence select="concat('#', tokenize($input, '#')[last()])"/>
201+
</xsl:function>
202+
203+
<!-- Copies an element whilst adding or replacing its 'xml:id' and 'source' attributes -->
204+
<xsl:template name="copy-with-updated-id-and-source">
205+
<xsl:param name="id" as="xs:string" required="yes"/>
206+
<xsl:param name="source" as="xs:string" required="yes"/>
207+
<xsl:copy>
208+
<xsl:attribute name="xml:id" select="$id"/>
209+
<xsl:if test="@source[. ne '']">
210+
<xsl:attribute name="source" select="$source"/>
211+
</xsl:if>
212+
<xsl:apply-templates select="@*[not(name(.) = ('xml:id', 'source'))]|node()"/>
213+
</xsl:copy>
214+
</xsl:template>
215+
216+
217+
<!-- Default: Identity trasform everything whilst updating the 'source' attribute -->
218+
<xsl:template match="node()|@*">
219+
<xsl:copy>
220+
<xsl:apply-templates select="@*[name(.) ne 'source']"/>
221+
<xsl:if test="@source[. ne '']">
222+
<xsl:attribute name="source" select="concat('#', substring-after(@source, '#'))"/>
223+
</xsl:if>
224+
<xsl:apply-templates select="node()"/>
225+
</xsl:copy>
226+
</xsl:template>
227+
228+
</xsl:stylesheet>

0 commit comments

Comments
 (0)