|
8 | 8 | version="3.0"> |
9 | 9 |
|
10 | 10 | <!-- Main template - apply three-pass normalization --> |
11 | | - <xsl:template match="/"> |
| 11 | + <xsl:template match="/" mode="ldh:normalize-rdfxml"> |
12 | 12 | <xsl:param name="base-uri" select="base-uri(.)" as="xs:anyURI"/> |
13 | 13 |
|
14 | 14 | <!-- First pass: normalize RDF/XML to canonical form --> |
15 | 15 | <xsl:variable name="normalized-rdf" as="document-node()"> |
16 | 16 | <xsl:document> |
17 | | - <xsl:apply-templates select="rdf:RDF" mode="ldh:normalize-RDF"/> |
| 17 | + <xsl:apply-templates select="rdf:RDF" mode="#current"/> |
18 | 18 | </xsl:document> |
19 | 19 | </xsl:variable> |
20 | 20 |
|
21 | 21 | <!-- Second pass: flatten all nested rdf:Description to top level --> |
22 | 22 | <xsl:variable name="flattened-rdf" as="document-node()"> |
23 | 23 | <xsl:document> |
24 | | - <xsl:apply-templates select="$normalized-rdf/rdf:RDF" mode="ldh:flatten-RDF"/> |
| 24 | + <xsl:apply-templates select="$normalized-rdf/rdf:RDF" mode="ldh:flatten-rdfxml"/> |
25 | 25 | </xsl:document> |
26 | 26 | </xsl:variable> |
27 | 27 |
|
|
67 | 67 | ======================================== --> |
68 | 68 |
|
69 | 69 | <!-- Copy rdf:RDF root element --> |
70 | | - <xsl:template match="rdf:RDF" mode="ldh:normalize-RDF"> |
| 70 | + <xsl:template match="rdf:RDF" mode="ldh:normalize-rdfxml"> |
71 | 71 | <xsl:copy> |
72 | 72 | <xsl:copy-of select="@*"/> |
73 | 73 | <xsl:apply-templates mode="#current"/> |
|
76 | 76 |
|
77 | 77 | <!-- Normalize typed nodes (e.g., <foaf:Person>) to rdf:Description with explicit rdf:type --> |
78 | 78 | <!-- Also handles rdf:ID attribute --> |
79 | | - <xsl:template match="rdf:RDF/*[@rdf:about or @rdf:nodeID or @rdf:ID][not(self::rdf:Description)]" mode="ldh:normalize-RDF"> |
| 79 | + <xsl:template match="rdf:RDF/*[@rdf:about or @rdf:nodeID or @rdf:ID][not(self::rdf:Description)]" mode="ldh:normalize-rdfxml"> |
80 | 80 | <rdf:Description> |
81 | 81 | <!-- Convert rdf:ID to rdf:about with fragment --> |
82 | 82 | <xsl:choose> |
|
103 | 103 |
|
104 | 104 | <!-- Already-normalized rdf:Description nodes - expand property attributes --> |
105 | 105 | <!-- Also handles rdf:ID attribute --> |
106 | | - <xsl:template match="rdf:Description[@rdf:about or @rdf:nodeID or @rdf:ID]" mode="ldh:normalize-RDF"> |
| 106 | + <xsl:template match="rdf:Description[@rdf:about or @rdf:nodeID or @rdf:ID]" mode="ldh:normalize-rdfxml"> |
107 | 107 | <xsl:copy> |
108 | 108 | <!-- Convert rdf:ID to rdf:about with fragment --> |
109 | 109 | <xsl:choose> |
|
127 | 127 | </xsl:template> |
128 | 128 |
|
129 | 129 | <!-- Normalize rdf:parseType="Literal" - keep as-is since it's already canonical --> |
130 | | - <xsl:template match="*[@rdf:parseType = 'Literal']" mode="ldh:normalize-RDF"> |
| 130 | + <xsl:template match="*[@rdf:parseType = 'Literal']" mode="ldh:normalize-rdfxml"> |
131 | 131 | <xsl:copy> |
132 | 132 | <xsl:copy-of select="@rdf:parseType"/> |
133 | 133 | <!-- Copy the XML content as-is --> |
|
136 | 136 | </xsl:template> |
137 | 137 |
|
138 | 138 | <!-- Normalize rdf:parseType="Collection" - create RDF list structure --> |
139 | | - <xsl:template match="*[@rdf:parseType = 'Collection']" mode="ldh:normalize-RDF"> |
| 139 | + <xsl:template match="*[@rdf:parseType = 'Collection']" mode="ldh:normalize-rdfxml"> |
140 | 140 | <xsl:choose> |
141 | 141 | <!-- Empty collection --> |
142 | 142 | <xsl:when test="not(*)"> |
|
222 | 222 | </xsl:template> |
223 | 223 |
|
224 | 224 | <!-- Normalize rdf:parseType="Resource" - create nested blank node that will be flattened later --> |
225 | | - <xsl:template match="*[@rdf:parseType = 'Resource']" mode="ldh:normalize-RDF"> |
| 225 | + <xsl:template match="*[@rdf:parseType = 'Resource']" mode="ldh:normalize-rdfxml"> |
226 | 226 | <xsl:variable name="blank-node-id" select="concat('b', generate-id())"/> |
227 | 227 |
|
228 | 228 | <!-- Create property element with nested blank node rdf:Description --> |
|
234 | 234 | </xsl:template> |
235 | 235 |
|
236 | 236 | <!-- Copy property elements that have rdf:resource or rdf:nodeID (object references) --> |
237 | | - <xsl:template match="rdf:Description/*[@rdf:resource or @rdf:nodeID]" mode="ldh:normalize-RDF"> |
| 237 | + <xsl:template match="rdf:Description/*[@rdf:resource or @rdf:nodeID]" mode="ldh:normalize-rdfxml"> |
238 | 238 | <xsl:copy> |
239 | 239 | <xsl:copy-of select="@rdf:resource | @rdf:nodeID"/> |
240 | 240 | </xsl:copy> |
241 | 241 | </xsl:template> |
242 | 242 |
|
243 | 243 | <!-- Handle RDF containers (Bag, Seq, Alt) --> |
244 | | - <xsl:template match="rdf:Bag | rdf:Seq | rdf:Alt" mode="ldh:normalize-RDF" priority="1"> |
| 244 | + <xsl:template match="rdf:Bag | rdf:Seq | rdf:Alt" mode="ldh:normalize-rdfxml" priority="1"> |
245 | 245 | <rdf:Description> |
246 | 246 | <xsl:copy-of select="@rdf:about | @rdf:nodeID"/> |
247 | 247 | <xsl:if test="not(@rdf:about or @rdf:nodeID)"> |
|
253 | 253 | </xsl:template> |
254 | 254 |
|
255 | 255 | <!-- Suppress default text node copying for containers --> |
256 | | - <xsl:template match="rdf:Bag/text() | rdf:Seq/text() | rdf:Alt/text()" mode="ldh:normalize-RDF"> |
| 256 | + <xsl:template match="rdf:Bag/text() | rdf:Seq/text() | rdf:Alt/text()" mode="ldh:normalize-rdfxml"> |
257 | 257 | <!-- Ignore whitespace text nodes in containers --> |
258 | 258 | <xsl:if test="normalize-space(.) != ''"> |
259 | 259 | <xsl:value-of select="."/> |
260 | 260 | </xsl:if> |
261 | 261 | </xsl:template> |
262 | 262 |
|
263 | 263 | <!-- Expand rdf:li to rdf:_N based on position --> |
264 | | - <xsl:template match="rdf:li" mode="ldh:normalize-RDF"> |
| 264 | + <xsl:template match="rdf:li" mode="ldh:normalize-rdfxml"> |
265 | 265 | <xsl:variable name="position" select="count(preceding-sibling::rdf:li) + 1" as="xs:integer"/> |
266 | 266 | <xsl:element name="rdf:_{$position}" namespace="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> |
267 | 267 | <xsl:copy-of select="@rdf:resource | @rdf:nodeID | @rdf:datatype | @xml:lang"/> |
|
277 | 277 | <!-- Copy property elements with literal values or datatype --> |
278 | 278 | <!-- Preserve xml:lang attribute --> |
279 | 279 | <!-- Only match properties with text content, not element children --> |
280 | | - <xsl:template match="rdf:Description/*[not(@rdf:resource) and not(@rdf:nodeID) and not(@rdf:parseType) and not(*)]" mode="ldh:normalize-RDF"> |
| 280 | + <xsl:template match="rdf:Description/*[not(@rdf:resource) and not(@rdf:nodeID) and not(@rdf:parseType) and not(*)]" mode="ldh:normalize-rdfxml"> |
281 | 281 | <xsl:copy> |
282 | 282 | <xsl:copy-of select="@rdf:datatype | @xml:lang"/> |
283 | 283 | <xsl:value-of select="."/> |
|
286 | 286 |
|
287 | 287 | <!-- Generic template to handle any property element that doesn't match more specific templates --> |
288 | 288 | <!-- This catches property elements from rdf:parseType="Resource" content and rdf:li --> |
289 | | - <xsl:template match="*[not(self::rdf:RDF) and not(self::rdf:Description) and not(self::rdf:li) and not(self::rdf:Bag) and not(self::rdf:Seq) and not(self::rdf:Alt)]" mode="ldh:normalize-RDF" priority="-1"> |
| 289 | + <xsl:template match="*[not(self::rdf:RDF) and not(self::rdf:Description) and not(self::rdf:li) and not(self::rdf:Bag) and not(self::rdf:Seq) and not(self::rdf:Alt)]" mode="ldh:normalize-rdfxml" priority="-1"> |
290 | 290 | <xsl:choose> |
291 | 291 | <!-- Property with rdf:resource or rdf:nodeID --> |
292 | 292 | <xsl:when test="@rdf:resource or @rdf:nodeID"> |
|
347 | 347 | ======================================== --> |
348 | 348 |
|
349 | 349 | <!-- Collect all rdf:Description elements at any level and make them direct children of rdf:RDF --> |
350 | | - <xsl:template match="rdf:RDF" mode="ldh:flatten-RDF"> |
| 350 | + <xsl:template match="rdf:RDF" mode="ldh:flatten-rdfxml"> |
351 | 351 | <xsl:copy> |
352 | 352 | <xsl:copy-of select="@*"/> |
353 | 353 | <!-- Process all rdf:Description elements (top-level and nested) --> |
|
0 commit comments