From: Lady <redacted> Date: Fri, 20 Sep 2024 03:21:16 +0000 (-0400) Subject: Apply attributes at every stage X-Git-Tag: 0.13.0~1 X-Git-Url: https://git.ladys.computer/Shushe/commitdiff_plain/23832d1a6f6bf4d2adce00d6e5ff65290aaa1ef1?hp=2c60920156e8a1ff1749f3e94316510d03a53a85 Apply attributes at every stage Previously, there was a lot of complicated logic to account for the fact that certain important attributes might not be added until the end of the transformation process (via `<书社:apply-attributes>` or `<书社:apply-attributes-to-root>`). It’s much simpler, conceptually, to just apply attributes after every transformation phase and not worry about them besides. This does mean that if an embed contains an `<书社:apply-attributes-to-root>` element, it _will_ almost definitely be applied when·ever that embed is embedded, before the next phase gets a chance to put a word in edge·wise. Presumably, tho, this is one of the main utilities of the `<书社:apply-attributes-to-root>` element in the first place, so maybe that is okay. This commit introduces a new `书社:finalize` mode for things wot used to be in the `书社:apply` mode but weren’t actually related to attribute application. --- diff --git a/README.markdown b/README.markdown index 503a163..af78725 100644 --- a/README.markdown +++ b/README.markdown @@ -585,7 +585,7 @@ Transforms are used to convert X·M·L files into their final output, media types into the appropriate H·T·M·L elements, and deletes `<html:style>` elements from the body of the document and moves them to the head. - This conversion happens during the application phase, after the main + This conversion happens during the finalization phase, after the main transformation. - **`transforms/metadata.xslt`:** @@ -604,7 +604,7 @@ Transforms are used to convert X·M·L files into their final output, - **`transforms/serialization.xslt`:** Replaces `<书社:serialize-xml>` elements with the (escaped) serialized X·M·L of their contents. - This replacement happens during the application phase, after most + This replacement happens during the finalization phase, after most other transformations have taken place. If a `@with-namespaces` attribute is provided, any name·space nodes @@ -730,8 +730,8 @@ It is especially useful in combination with output wrapping. In both cases, attributes from various sources are combined with white·space between them. -Attribute application takes place after all ordinary transforms have - completed. +Attribute application takes place after each stage of the + transformation, including after the initial embedding phase. Both elements ignore attributes in the `xml:` name·space, except for `@xml:lang`, which ignores all but the first definition (including diff --git a/lib/catalog2transform.xslt b/lib/catalog2transform.xslt index 10a5479..68fb3a2 100644 --- a/lib/catalog2transform.xslt +++ b/lib/catalog2transform.xslt @@ -19,6 +19,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:catalog="urn:oasis:names:tc:entity:xmlns:xml:catalog" xmlns:exsl="http://exslt.org/common" + xmlns:exslfunc="http://exslt.org/functions" xmlns:exslstr="http://exslt.org/strings" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:nie="http://www.semanticdesktop.org/ontologies/2007/01/19/nie#" @@ -51,26 +52,50 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </if> </for-each> </variable> - <xslt:transform exclude-result-prefixes="nie nfo" extension-element-prefixes="exsl exslstr" version="1.0"> + <xslt:transform exclude-result-prefixes="nie nfo" extension-element-prefixes="exsl exslfunc exslstr" version="1.0"> <xslt:param name="BUILDTIME" select="'1972-12-31T00:00:00Z'"/> <xslt:param name="IDENTIFIER" select="false()"/> <xslt:param name="SRCREV" select="false()"/> <xslt:param name="THISREV" select="false()"/> + <element name="exslfunc:function"> + <attribute name="name"> + <text>书社:document-with-attributes-applied</text> + </attribute> + <xslt:param name="document" select="/.."/> + <xslt:param name="and-version" select="false()"/> + <xslt:variable name="application-result-fragment"> + <xslt:variable name="result-nodes" select="$document/node()[not(self::书社:apply-attributes-to-root)]|$document/书社:apply-attributes-to-root//node()[not(self::书社:apply-attributes-to-root) and not(ancestor::*[not(self::书社:apply-attributes-to-root)])]"/> + <xslt:variable name="significant-nodes" select="$result-nodes/descendant-or-self::*[not(self::书社:apply-attributes) and not(ancestor::*[not(self::书社:apply-attributes)])]"/> + <xslt:variable name="root-with-attributes"> + <xslt:call-template name="书社:apply-attributes"> + <xslt:with-param name="and-version" select="$and-version"/> + <xslt:with-param name="context-nodes" select="$document//书社:apply-attributes-to-root"/> + <xslt:with-param name="destination-nodes" select="$result-nodes"/> + </xslt:call-template> + </xslt:variable> + <xslt:apply-templates select="exsl:node-set($root-with-attributes)" mode="书社:apply"/> + </xslt:variable> + <element name="exslfunc:result"> + <attribute name="select"> + <text>exsl:node-set($application-result-fragment)</text> + </attribute> + </element> + </element> <xslt:variable name="书社:source" select="/"/> <xslt:variable name="书社:about-fragment"> <apply-templates select="document($METADATA)" mode="书社:literally"> - <with-param name="extension-element-namespaces" select="'http://exslt.org/common http://exslt.org/strings'"/> + <with-param name="extension-element-namespaces" select="'http://exslt.org/common http://exslt.org/functions http://exslt.org/strings'"/> </apply-templates> </xslt:variable> <xslt:variable name="书社:about" select="exsl:node-set($书社:about-fragment)"/> <xslt:variable name="书社:expansion-fragment"> <xslt:apply-templates select="$书社:source/node()" mode="书社:expand"/> </xslt:variable> - <xslt:variable name="书社:expansion" select="exsl:node-set($书社:expansion-fragment)"/> + <xslt:variable name="书社:expansion" select="书社:document-with-attributes-applied(exsl:node-set($书社:expansion-fragment))"/> <xslt:variable name="书社:result-fragment"> <xslt:apply-templates select="$书社:expansion/node()"/> </xslt:variable> - <xslt:variable name="书社:result" select="exsl:node-set($书社:result-fragment)"/> + <xslt:variable name="书社:result" select="书社:document-with-attributes-applied(exsl:node-set($书社:result-fragment))"/> <xslt:variable name="书社:destination" select="string($书社:about//*[@rdf:about=$IDENTIFIER]/@书社vocab:destination)"/> <for-each select="//catalog:uri"> <xslt:include href="{@uri}"> @@ -261,105 +286,17 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </html:body> </html:html> </xslt:template> - <xslt:template match="/" priority="1"> - <xslt:variable name="result-nodes" select="$书社:result/node()[not(self::书社:apply-attributes-to-root)]|$书社:result/书社:apply-attributes-to-root//node()[not(self::书社:apply-attributes-to-root) and not(ancestor::*[not(self::书社:apply-attributes-to-root)])]"/> - <xslt:variable name="significant-nodes" select="$result-nodes/descendant-or-self::*[not(self::书社:apply-attributes) and not(ancestor::*[not(self::书社:apply-attributes)])]"/> - <xslt:variable name="root-with-attributes"> - <xslt:choose> - <xslt:when test="not($significant-nodes/self::html:*) or $significant-nodes/self::书社:*[local-name()='raw-text' or local-name()='base64-binary' or local-name()='archive'] or $significant-nodes/@书社:disable-output-wrapping or $书社:result//书社:apply-attributes-to-root/@书社:disable-output-wrapping"> - <xslt:call-template name="书社:apply-attributes"> - <xslt:with-param name="and-version" select="true()"/> - <xslt:with-param name="context-nodes" select="$书社:result//书社:apply-attributes-to-root"/> - <xslt:with-param name="destination-nodes" select="$result-nodes"/> - </xslt:call-template> - </xslt:when> - <xslt:otherwise> - <xslt:variable name="wrapped-result"> - <xslt:call-template name="书社:wrap"> - <xslt:with-param name="nodes" select="$result-nodes"/> - </xslt:call-template> - </xslt:variable> - <xslt:call-template name="书社:apply-attributes"> - <xslt:with-param name="and-version" select="true()"/> - <xslt:with-param name="context-nodes" select="$书社:result//书社:apply-attributes-to-root"/> - <xslt:with-param name="destination-nodes" select="exsl:node-set($wrapped-result)/node()"/> - </xslt:call-template> - </xslt:otherwise> - </xslt:choose> + <xslt:template match="/"> + <xslt:variable name="finalization-fragment"> + <xslt:apply-templates select="$书社:result" mode="书社:finalize"/> </xslt:variable> - <xslt:apply-templates select="exsl:node-set($root-with-attributes)/node()" mode="书社:apply"/> + <xslt:copy-of select="书社:document-with-attributes-applied(exsl:node-set($finalization-fragment))"/> </xslt:template> <xslt:template match="@*|node()" priority="-1"> <xslt:copy> <xslt:apply-templates select="@*|node()"/> </xslt:copy> </xslt:template> - <xslt:template match="@书社:destination|@书社:disable-output-wrapping" mode="书社:apply" priority="1"/> - <xslt:template match="书社:archive" mode="书社:apply" priority="1"> - <xslt:copy> - <xslt:apply-templates select="@*" mode="书社:apply"/> - <xslt:for-each select="node()"> - <xslt:choose> - <xslt:when test="self::*"> - <xslt:variable name="component-fragment"> - <xslt:copy> - <xslt:choose> - <xslt:when test="self::html:*"> - <xslt:variable name="existing-types" select="exslstr:tokenize(@itemtype)"/> - <xslt:attribute name="itemscope">itemscope</xslt:attribute> - <xslt:attribute name="itemtype"> - <xslt:for-each select="$existing-types/token"> - <xslt:if test="position()!=1"> - <xslt:text> - <text> </text> - </xslt:text> - </xslt:if> - <xslt:value-of select="."/> - </xslt:for-each> - <xslt:if test="not($existing-types/token[string()='&书社;:embed' or string()='&书社;:document'])"> - <xslt:if test="$existing-types/token"> - <xslt:text> - <text> </text> - </xslt:text> - </xslt:if> - <xslt:text> - <text>&书社;:document</text> - </xslt:text> - </xslt:if> - </xslt:attribute> - <xslt:copy-of select="@*[not(namespace-uri()='' and (local-name()='itemscope' or local-name()='itemtype'))]|node()"/> - </xslt:when> - <xslt:otherwise> - <xslt:copy-of select="@*|node()"/> - </xslt:otherwise> - </xslt:choose> - </xslt:copy> - </xslt:variable> - <xslt:variable name="wrapped-component-fragment"> - <xslt:for-each select="exsl:node-set($component-fragment)/*"> - <xslt:variable name="result-nodes" select="self::*[not(self::书社:apply-attributes-to-root)]|self::书社:apply-attributes-to-root//node()[not(self::书社:apply-attributes-to-root) and not(ancestor::*[not(self::书社:apply-attributes-to-root)])]"/> - <xslt:variable name="significant-nodes" select="$result-nodes/descendant-or-self::*[not(self::书社:apply-attributes) and not(ancestor::*[not(self::书社:apply-attributes)])]"/> - <xslt:choose> - <xslt:when test="not($significant-nodes/self::html:*) or $significant-nodes/self::书社:*[local-name()='raw-text' or local-name()='base64-binary' or local-name()='archive'] or $significant-nodes/@书社:disable-output-wrapping"> - <xslt:copy-of select="."/> - </xslt:when> - <xslt:otherwise> - <xslt:call-template name="书社:wrap"> - <xslt:with-param name="nodes" select="$result-nodes"/> - </xslt:call-template> - </xslt:otherwise> - </xslt:choose> - </xslt:for-each> - </xslt:variable> - <xslt:apply-templates select="exsl:node-set($wrapped-component-fragment)/node()" mode="书社:apply"/> - </xslt:when> - <xslt:otherwise> - <xslt:apply-templates select="." mode="书社:apply"/> - </xslt:otherwise> - </xslt:choose> - </xslt:for-each> - </xslt:copy> - </xslt:template> <xslt:template match="书社:apply-attributes" mode="书社:apply" priority="1"> <xslt:variable name="children"> <xslt:apply-templates mode="书社:apply"/> @@ -503,6 +440,79 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one </xslt:copy> </xslt:template> <xslt:template match="text()" mode="书社:header"/> + <xslt:template match="书社:archive" mode="书社:finalize" priority="1"> + <xslt:copy> + <xslt:apply-templates select="@*" mode="书社:finalize"/> + <xslt:for-each select="node()"> + <xslt:choose> + <xslt:when test="self::*"> + <xslt:variable name="component-fragment"> + <xslt:copy> + <xslt:choose> + <xslt:when test="self::html:*"> + <xslt:variable name="existing-types" select="exslstr:tokenize(@itemtype)"/> + <xslt:attribute name="itemscope">itemscope</xslt:attribute> + <xslt:attribute name="itemtype"> + <xslt:for-each select="$existing-types/token"> + <xslt:if test="position()!=1"> + <xslt:text> + <text> </text> + </xslt:text> + </xslt:if> + <xslt:value-of select="."/> + </xslt:for-each> + <xslt:if test="not($existing-types/token[string()='&书社;:embed' or string()='&书社;:document'])"> + <xslt:if test="$existing-types/token"> + <xslt:text> + <text> </text> + </xslt:text> + </xslt:if> + <xslt:text> + <text>&书社;:document</text> + </xslt:text> + </xslt:if> + </xslt:attribute> + <xslt:copy-of select="@*[not(namespace-uri()='' and (local-name()='itemscope' or local-name()='itemtype'))]|node()"/> + </xslt:when> + <xslt:otherwise> + <xslt:copy-of select="@*|node()"/> + </xslt:otherwise> + </xslt:choose> + </xslt:copy> + </xslt:variable> + <xslt:variable name="finalization-fragment"> + <xslt:apply-templates select="exsl:node-set($component-fragment)" mode="书社:finalize"/> + </xslt:variable> + <xslt:copy-of select="书社:document-with-attributes-applied(exsl:node-set($finalization-fragment))"/> + </xslt:when> + <xslt:otherwise> + <xslt:apply-templates select="." mode="书社:finalize"/> + </xslt:otherwise> + </xslt:choose> + </xslt:for-each> + </xslt:copy> + </xslt:template> + <xslt:template match="@书社:destination|@书社:disable-output-wrapping" mode="书社:finalize" priority="1"/> + <xslt:template match="/" mode="书社:finalize"> + <xslt:choose> + <xslt:when test="not(html:*) or 书社:raw-text or 书社:base64-binary or 书社:archive or */@书社:disable-output-wrapping"> + <xslt:apply-templates mode="书社:finalize"/> + </xslt:when> + <xslt:otherwise> + <xslt:variable name="wrapped-result"> + <xslt:call-template name="书社:wrap"> + <xslt:with-param name="nodes" select="node()"/> + </xslt:call-template> + </xslt:variable> + <xslt:apply-templates select="exsl:node-set($wrapped-result)/node()" mode="书社:finalize"/> + </xslt:otherwise> + </xslt:choose> + </xslt:template> + <xslt:template match="@*|node()" mode="书社:finalize" priority="-1"> + <xslt:copy> + <xslt:apply-templates select="@*|node()" mode="书社:finalize"/> + </xslt:copy> + </xslt:template> <xslt:template match="text()" mode="书社:footer"/> <xslt:template match="text()" mode="书社:metadata"/> <xslt:output method="xml" encoding="UTF-8" cdata-section-elements="html:script html:style html:textarea 书社:raw-output 书社:raw-text"/> diff --git a/transforms/asset.xslt b/transforms/asset.xslt index 38d2e67..2b43595 100644 --- a/transforms/asset.xslt +++ b/transforms/asset.xslt @@ -23,23 +23,23 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one version="1.0" > <书社:id>urn:fdc:ladys.computer:20231231:Shu1She4:asset.xslt</书社:id> - <template match="html:style[&wrapped; and not(ancestor::html:head)]|html:object[@type='text/css' and &wrapped;]" mode="书社:apply" priority="0"/> - <template match="html:object[@type='text/javascript']" mode="书社:apply" priority="0"> + <template match="html:style[&wrapped; and not(ancestor::html:head)]|html:object[@type='text/css' and &wrapped;]" mode="书社:finalize" priority="0"/> + <template match="html:object[@type='text/javascript']" mode="书社:finalize" priority="0"> <html:script type="{@type}" src="{@data}"> <copy-of select="@书社:identifier"/> </html:script> </template> - <template match="html:object[starts-with(@type, 'audio/')]" mode="书社:apply" priority="0"> + <template match="html:object[starts-with(@type, 'audio/')]" mode="书社:finalize" priority="0"> <html:audio controls="" src="{@data}"> <copy-of select="@书社:identifier"/> </html:audio> </template> - <template match="html:object[starts-with(@type, 'image/') and not(@type='image/svg+xml')]" mode="书社:apply" priority="0"> + <template match="html:object[starts-with(@type, 'image/') and not(@type='image/svg+xml')]" mode="书社:finalize" priority="0"> <html:img src="{@data}"> <copy-of select="@书社:identifier|@width|@height"/> </html:img> </template> - <template match="html:object[starts-with(@type, 'video/')]" mode="书社:apply" priority="0"> + <template match="html:object[starts-with(@type, 'video/')]" mode="书社:finalize" priority="0"> <html:video controls="" src="{@data}"> <copy-of select="@书社:identifier|@width|@height"/> </html:video> diff --git a/transforms/serialization.xslt b/transforms/serialization.xslt index ce986ff..13c47b8 100644 --- a/transforms/serialization.xslt +++ b/transforms/serialization.xslt @@ -22,10 +22,10 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one > <import href="../lib/serialize.xslt"/> <书社:id>urn:fdc:ladys.computer:20231231:Shu1She4:serialization.xslt</书社:id> - <template match="书社:serialize-xml" mode="书社:apply" priority="1"> + <template match="书社:serialize-xml" mode="书社:finalize" priority="1"> <variable name="namespaces" select="namespace::*"/> <variable name="contents"> - <apply-templates mode="书社:apply"/> + <apply-templates mode="书社:finalize"/> </variable> <variable name="passthru-namespaces" select="exslstr:tokenize(string(@with-namespaces))"/> <apply-templates select="exsl:node-set($contents)" mode="书社:serialize">