]> Lady’s Computer - Shushe/commitdiff
Allow creation of tarballs 0.7.0
authorLady <redacted>
Wed, 10 Apr 2024 19:53:11 +0000 (15:53 -0400)
committerLady <redacted>
Wed, 10 Apr 2024 19:53:11 +0000 (15:53 -0400)
This is useful when using ⛩️📰 书社 directly as a static site
generator to provide archive downloads (archives are not compressed; it
is assumed that they will be gzipped over the wire). This requires
a recursive call to Make for each archive file, which performs the
following steps :—

- Extracts all of the elements slated for archiving into separate
  files.

- Restarts.

- Processes the resulting extracted files and then archives them.

The extraction step in particular is somewhat convoluted; it requires
dynamically generating a transform which has the appropriate
`<exsl:document>` elements for a given source file, and then applying
that transform in a second call to `xsltproc`.

X·M·L outputs are now passed through an extra call to `xmllint` to
remove any unnecessary namespace attributes instead of just symlinked;
the symlinks weren’t compatible with archiving anyway.

GNUmakefile
README.markdown
lib/archive2extractor.xslt [new file with mode: 0644]
lib/catalog2transform.xslt

index efa5c19708b56ffef9adcfd73fc0e3e81a46b552..944f6dec4d1f877ce6ad4e47bdd8a1de6f05185a 100644 (file)
@@ -30,6 +30,7 @@ override define makefileinfo
 ║│ • mkdir (requires support for `-p´)                        │║
 ║│ • mv                                                       │║
 ║│ • od (requires support for `-t x1´)                        │║
+║│ • pax (only when generating archives)                      │║
 ║│ • printf                                                   │║
 ║│ • rm                                                       │║
 ║│ • sed                                                      │║
@@ -105,6 +106,7 @@ LN := ln
 MKDIR := mkdir
 MV := mv
 OD := od
+PAX := pax
 PRINTF := printf
 RM := rm
 SED := sed
@@ -120,6 +122,16 @@ XMLCATALOG := xmlcatalog
 XMLLINT := xmllint
 XSLTPROC := xsltproc
 
+# This variable is not used in normal execution.
+#
+# In the archiving `MODE´, it provides the X·M·L file from which the archive should be constructed.
+SRC :=
+
+# This variable is not used in normal execution.
+#
+# In the archiving `MODE´, it provides a user‐friendly name for the archive.
+NAME :=
+
 # The directory which contains the source files.
 #
 # Multiple directories can be given so long as files with the same name do not exist in each.
@@ -134,14 +146,20 @@ SRCDIR := sources
 INCLUDEDIR := sources/includes
 
 # The directory in which to generate temporary buildfiles.
+#
+# This variable is also used by the archiving `MODE´.
 BUILDDIR := build
 
 # The directory into which to output files on `make install´.
+#
+# This variable is also used by the archiving `MODE´.
 DESTDIR := public
 
 # The location of this Makefile (and related ⛩️📰 书社 files), relative to the current working directory.
 #
 # By default, this is inferred from the variable `MAKEFILE_LIST´.
+#
+# This variable is also used by the archiving `MODE´.
 THISDIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
 
 # Configuration of `find´.
@@ -185,13 +203,25 @@ SRCREV := $(shell $(GIT) describe 2> /dev/null || $(GIT) rev-parse HEAD 2> /dev/
 endif
 endif
 
+# The mode in which to run this make·file.
+# Modes essentially allow for the combination of multiple conceptual make·files into a single source.
+#
+# The following modes are available :—
+#
+# • ‹ urn:fdc:ladys.computer:20231231:Shu1She4:mode:default ›:
+#   The default mode; typical Shushe behaviours.
+#
+# • ‹ urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive ›:
+#   Generates archive files from parse results.
+MODE := urn:fdc:ladys.computer:20231231:Shu1She4:mode:default
+
 # Set to a non·empty value to print all commands as they run.
 VERBOSE :=
 
 # The default target for this makefile.
 .DEFAULT_GOAL := all
 
-# ━ § BEGIN MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+# ━ § BEGIN SHARED MAKE·FILE CONSTRUCTS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
 # ─ ¶ Non‐Recipe Variable Definitions ─────────────────────────────────
 
@@ -216,6 +246,26 @@ override quote = '$(subst ','"'"',$1)'
 # Outputs an `@´ to silence rules, unless `VERBOSE´ is nonempty.
 override silent := $(if $(VERBOSE),,@)
 
+# ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
+
+# (callable) Check to see if the given directory exists and create it if not.
+override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(call quote,$1); fi
+
+# (callable) Test if the provided xpath expression matches the provided document.
+override xpath = $(XMLLINT) --xpath $(call quote,$1) $(call quote,$2) > /dev/null 2> /dev/null
+
+# (callable) Extract the value of the text nodes in the provided X·M·L document and print them to `stdout´.
+override extracttext = $(PRINTF) '%s' '<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"><output method="text" encoding="UTF-8"/></transform>' | $(XSLTPROC) - $(call quote,$1)
+
+# (callable) Process the provided transformation result and output the result to the provided location, given the provided relative path.
+override processresultto = if $(call xpath,/*[local-name()="raw-text" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(RM) -f $(call quote,$2); $(call extracttext,$1) > $(call quote,$2); elif $(call xpath,/*[local-name()="base64-binary" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(RM) -f $(call quote,$2); $(call extracttext,$1) | $(TR) -d '\t\n\f\r ' | $(UUDECODE) -m -r > $(call quote,$2); elif $(call xpath,/*[local-name()="archive" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$1); then $(RM) -f $(call quote,$2); $(MAKE) -f $(call quote,$(abspath $(THISDIR)/GNUmakefile)) $(call quote,$2) NAME=$(call quote,$3) SRC=$(call quote,$1) BUILDDIR=$(call quote,$(BUILDDIR)/archive/$3) DESTDIR=$(call quote,$(patsubst %/,%,$(dir $2))) MODE='urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive'; else $(RM) -f $(call quote,$2); $(XMLLINT) --nsclean $(call quote,$1) > $(call quote,$2); fi
+
+# ━ § BEGIN DEFAULT MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+ifeq ($(MODE),urn:fdc:ladys.computer:20231231:Shu1She4:mode:default)
+
+# ─ ¶ Non‐Recipe Variable Definitions ─────────────────────────────────
+
 # (callable) Test to see if the prerequisites provided by the second argument matches the value in the file corresponding to the first argument in `$(BUILDDIR)/lastprereqs´.
 # If not, save the new value and then add FORCE.
 # Return them regardless.
@@ -388,9 +438,6 @@ endif
 
 # ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
 
-# (callable) Check to see if the given directory exists and create it if not.
-override ensuredirectory = if $(TEST) ! -d $(call quote,$1); then $(MKDIR) -p $(call quote,$1); fi
-
 # (callable) Get the identifier for the given parser or transform.
 override id = $(XMLLINT) --xpath '/*/*[local-name()="id" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"]/text()[1]' $(call quote,$1) 2> /dev/null || $(PRINTF) '%s\n' $(call quote,about:shushe?$(or $2,unknown)=$(call pathenc,$(basename $(notdir $1))))
 
@@ -404,12 +451,6 @@ override wrapplaintext = $(TR) '\000\013\014' '\032\011\012' < $(call quote,$1)
 # This isn’t a perfect substitution (it makes some assumptions about the format of the underlying X·M·L), but it should be workable for most sensible, welformed files.
 override serializexml = $(SED) "$$($(PRINTF) '%b' '/<?xml[ \t]\\{1,\\}version=[\0042\0047]1.1/,$${ s/<?xml[^>]*?>/<!--<?xml version=\00421.1\0042?>-->/\n s/&\0043x0*[1-8BCEFbcef];/\0302\0221/g\n s/&\0043x0*1[0-9A-Fa-f];/\0302\0221/g\n s/&\00430*[1-8];/\0302\0221/g\n s/&\00430*1[124-9];/\0302\0221/g\n s/&\00430*2[0-9];/\0302\0221/g\n s/&\00430*3[01];/\0302\0221/g\n}')" < $(call quote,$1) | $(SED) "$$(PRINTF '%b' ':a\n/^\\n*$$/{ $$d\n N\n ba\n}')"
 
-# (callable) Test if the provided xpath expression matches the provided document.
-override xpath = $(XMLLINT) --xpath $(call quote,$1) $(call quote,$2) > /dev/null 2> /dev/null
-
-# (callable) Extract the value of the text nodes in the provided X·M·L document and print them to `stdout´.
-override extracttext = $(PRINTF) '%s' '<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0"><output method="text" encoding="UTF-8"/></transform>' | $(XSLTPROC) - $(call quote,$1)
-
 # ─ ¶ Phony Targets ───────────────────────────────────────────────────
 
 # Compile all files, or error if any are recursive.
@@ -563,7 +604,7 @@ $(call compiled,$(compilablefiles)) : $(BUILDDIR)/results/% : $$(call parsed,$$(
 $(call built,$(compilablefiles)) : $(BUILDDIR)/public/% : $(BUILDDIR)/results/%
        @$(PRINTF) '%s\n' $(call quote,Building </$*>…)
        $(silent)$(call ensuredirectory,$(dir $@))
-       $(silent)if $(call xpath,/*[local-name()="raw-text" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$<); then $(RM) -f $(call quote,$@); $(call extracttext,$<) > $(call quote,$@); elif $(call xpath,/*[local-name()="base64-binary" and namespace-uri()="urn:fdc:ladys.computer:20231231:Shu1She4"],$<); then $(RM) -f $(call quote,$@); $(call extracttext,$<) | $(TR) -d '\t\n\f\r ' | $(UUDECODE) -m -r > $(call quote,$@); else $(LN) -s -f $(call quote,$(subst $(space),,$(foreach component,$(subst /, ,$*),../))results/$*) $(call quote,$@); fi
+       $(silent)$(call processresultto,$<,$@,$*)
 $(call built,$(filter $(assetfiles),$(sourcefiles))) : $(BUILDDIR)/public/% : $$(call unbuilt,$$@)
        @$(PRINTF) '%s\n' $(call quote,Building </$*>…)
        $(silent)$(call ensuredirectory,$(dir $@))
@@ -574,3 +615,63 @@ $(call installed,$(recursivefiles) $(installablefiles)) : $(DESTDIR)/% : $(BUILD
        @$(PRINTF) '%s\n' $(call quote,Installing </$*>…)
        $(silent)$(call ensuredirectory,$(dir $@))
        $(silent)$(CP) $(call quote,$<) $(call quote,$@)
+
+# ━ § BEGIN ARCHIVE MAKE·FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+else ifeq ($(MODE),urn:fdc:ladys.computer:20231231:Shu1She4:mode:archive)
+
+# ─ ¶ Non‐Recipe Variable Definitions ─────────────────────────────────
+
+# Get the list of files in the archive.
+ifneq ($(wildcard $(BUILDDIR)/index),)
+override archivefiles := $(patsubst ./extracted/%,%,$(shell $(CAT) $(call quote,$(BUILDDIR)/index)))
+endif
+
+# ─ ¶ Recipe Variable Definitions ─────────────────────────────────────
+
+# ─ ¶ Phony Targets ───────────────────────────────────────────────────
+
+# ─ ¶ Special Targets ─────────────────────────────────────────────────
+
+# Reload this make·file if the archive components have changed.
+$(THISDIR)/GNUmakefile : $(BUILDDIR)/index
+       $(silent)$(TOUCH) $(THISDIR)/GNUmakefile
+       @$(PRINTF) '%b\n' $(call quote,\0033[1mArchive components for </$(NAME)> updated. Restarting…\0033[22m)
+
+# ─ ¶ Build Targets ───────────────────────────────────────────────────
+
+# Build the extractor transform for extracting the contents of the archive source file.
+$(BUILDDIR)/extractor.xslt : $(SRC) $(THISDIR)/lib/archive2extractor.xslt
+       $(silent)$(call ensuredirectory,$(dir $@))
+       $(silent)$(XSLTPROC) -o $(call quote,$@) $(call quote,$(THISDIR)/lib/archive2extractor.xslt) $(call quote,$<)
+
+# Use the extractor transform to extract the archive source file out into its components.
+#
+# This target sleeps for 1 second to ensure the resulting index will always be newer than this make·file.
+$(BUILDDIR)/index : $(BUILDDIR)/extractor.xslt $(SRC)
+       @$(PRINTF) '%s\n' $(call quote,Extracting components for </$(NAME)>…)
+       $(silent)$(SLEEP) 1
+       $(silent)$(XSLTPROC) -o $(call quote,$@) --writesubtree $(call quote,$(dir $@)) $(call quote,$<) $(call quote,$(SRC))
+
+# All archive components are extracted alongside the index.
+$(foreach file,$(archivefiles),$(BUILDDIR)/extracted/$(file)) : $(BUILDDIR)/index ;
+
+# Process each extractor component into its final form.
+$(foreach file,$(archivefiles),$(BUILDDIR)/files/$(file)) : $(BUILDDIR)/files/% : $(BUILDDIR)/extracted/%
+       @$(PRINTF) '%s\n' $(call quote,Building </$(NAME)/$*>…)
+       $(silent)$(call ensuredirectory,$(dir $@))
+       $(silent)$(call processresultto,$<,$@,$*)
+
+# Archive all components in the file to the destination.
+#
+# This is a match‐anything target, with the assumption that this make·file is being called recursively from the default mode.
+$(DESTDIR)/% : $(foreach file,$(archivefiles),$(BUILDDIR)/files/$(file))
+       @$(PRINTF) '%s\n' $(call quote,Archiving </$(NAME)>…)
+       $(silent)$(call ensuredirectory,$(dir $@))
+       $(silent)cd $(call quote,$(BUILDDIR)/files); $(PRINTF) '%s\n' $(foreach file,$(archivefiles),$(call quote,$(file))) | $(PAX) -w > $(call quote,$(abspath $@))
+
+# ━ § END DEFINED MAKE·FILE MODES ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+else
+$(error Unrecognized MODE: $(MODE))
+endif
index 7c663be305086a76c6d33937a012c7eb339e4ce9..55d6f8f8d7c31ba42d6477c2f2ef8f043696d45a 100644 (file)
@@ -121,6 +121,7 @@ In every case, you may supply your own implementation by overriding the
 - `mkdir` (requires support for `-p`)
 - `mv`
 - `od` (requires support for `-t x1`)
+- `pax` (only when generating archives)
 - `printf`
 - `rm`
 - `sed`
@@ -528,7 +529,8 @@ Output wrapping can be entirely disabled by adding a
   `@书社:disable-output-wrapping` attribute to the top‐level element in
   the result tree.
 It will not be performed on outputs whose root elements are
-  `<书社:raw-text>` or `<书社:base64-binary>` (described below).
+  `<书社:archive>`, `<书社:base64-binary>`, or `<书社:raw-text>`
+  (described below).
 
 ## Applying Attributes
 
@@ -558,15 +560,24 @@ There are a few special elements in the `书社:` namespace which, if
   ⛩️📰 书社 to produce something other than an X·M·L file.
 They are :⁠—
 
-- **`<书社:raw-text>`:**
-  A plaintext (U·T·F‐8) file will be produced from the text nodes in
-    the transformation result.
+- **`<书社:archive>`:**
+  Each child element with a `@书社:archived-as` attribute will be
+    archived as a separate file in a resulting tarball (this attribute
+    gives the file name).
+  These elements will be processed the same as the root elements of any
+    other file (e·g, they will be wrapped; they can themselves specify
+    non X·M·L output types, ⁊·c).
+  Other child elements will be ignored.
 
 - **`<书社:base64-binary>`:**
   The text nodes in the transformation result will, after removing all
     Ascii whitespace, be treated as a Base·64 string, which is then
     decoded.
 
+- **`<书社:raw-text>`:**
+  A plaintext (U·T·F‐8) file will be produced from the text nodes in
+    the transformation result.
+
 ## License
 
 This repository conforms to [REUSE][].
diff --git a/lib/archive2extractor.xslt b/lib/archive2extractor.xslt
new file mode 100644 (file)
index 0000000..b5fb703
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<!--
+SPDX-FileCopyrightText: 2024 Lady <https://www.ladys.computer/about/#lady>
+SPDX-License-Identifier: MPL-2.0
+-->
+<!--
+⁌ ⛩️📰 书社 ∷ lib/archive2extractor.xslt
+
+© 2024 Lady [@ Lady’s Computer].
+
+This Source Code Form is subject to the terms of the Mozilla Public License, v 2.0.
+If a copy of the M·P·L was not distributed with this file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+-->
+<transform
+       xmlns="http://www.w3.org/1999/XSL/Transform"
+       xmlns:xslt="http://www.w3.org/1999/XSL/TransformAlias"
+       xmlns:书社="urn:fdc:ladys.computer:20231231:Shu1She4"
+       version="1.0"
+>
+       <namespace-alias stylesheet-prefix="xslt" result-prefix="#default"/>
+       <template match="/">
+               <xslt:transform
+                       xmlns:exsl="http://exslt.org/common"
+                       extension-element-prefixes="exsl"
+                       version="1.0"
+               >
+                       <xslt:template match="/">
+                               <for-each select="书社:archive/*[@书社:archived-as and not(starts-with(@书社:archived-as, '../') or contains(@书社:archived-as, '/../'))]">
+                                       <variable name="href">
+                                               <text>./extracted/</text>
+                                               <choose>
+                                                       <when test="starts-with(@书社:archived-as, './')">
+                                                               <value-of select="substring-after(@书社:archived-as, './')"/>
+                                                       </when>
+                                                       <otherwise>
+                                                               <value-of select="@书社:archived-as"/>
+                                                       </otherwise>
+                                               </choose>
+                                       </variable>
+                                       <exsl:document href="{$href}" method="xml" encoding="UTF-8">
+                                               <xslt:variable name="href">
+                                                       <value-of select="@书社:archived-as"/>
+                                               </xslt:variable>
+                                               <xslt:copy-of select="书社:archive/*[@书社:archived-as=$href][1]"/>
+                                       </exsl:document>
+                                       <xslt:text>
+                                               <value-of select="$href"/>
+                                               <text>&#xA;</text>
+                                       </xslt:text>
+                               </for-each>
+                       </xslt:template>
+                       <xslt:output method="text" encoding="UTF-8"/>
+               </xslt:transform>
+       </template>
+       <output method="xml" encoding="UTF-8"/>
+</transform>
index a2af62f2e66c535fb4ef73085565e6da6b95b0ae..e5ce32186348a6bc2e3757ffdefa9019ebbcd5dd 100644 (file)
@@ -118,6 +118,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                                                        <xslt:choose>
                                                                                <xslt:when test="@namespace-uri='&xml;'"/>
                                                                                <xslt:when test="$context[self::html:* or self::svg:*] and @namespace-uri='' and @local-name='lang'"/>
+                                                                               <xslt:when test="@namespace-uri='&书社;' and @local-name='archived-as' and not($context-nodes/ancestor::*[not(self::书社:apply-attributes-to-root or self::书社:apply-attributes)][1][self::书社:archive])"/>
                                                                                <xslt:when test="@namespace-uri='&书社;' and (@local-name='destination' or @local-name='disable-output-wrapping' or @local-name='version')"/>
                                                                                <xslt:when test="preceding-sibling::*[@local-name=current()/@local-name and @namespace-uri=current()/@namespace-uri]"/>
                                                                                <xslt:otherwise>
@@ -174,6 +175,11 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                </xslt:variable>
                                <html:html>
                                        <xslt:copy-of select="$nodes[self::html:html]/@*"/>
+                                       <xslt:if test="not($nodes[self::html:html]/@书社:archived-as) and $nodes/@书社:archived-as">
+                                               <xslt:attribute name="书社:archived-as">
+                                                       <xslt:value-of select="$nodes/@书社:archived-as"/>
+                                               </xslt:attribute>
+                                       </xslt:if>
                                        <xslt:if test="not($nodes[self::html:html]/@lang) and $nodes[self::html:*]/@lang|$nodes[self::svg:*]/@lang|$nodes/@xml:lang">
                                                <xslt:attribute name="lang">
                                                        <xslt:value-of select="$nodes[self::html:*]/@lang|$nodes[self::svg:*]/@lang|$nodes/@xml:lang"/>
@@ -232,7 +238,7 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                <xslt:variable name="result-nodes" select="exsl:node-set($书社:result)/node()[not(self::书社:apply-attributes-to-root)]|exsl:node-set($书社:result)/书社:apply-attributes-to-root/descendant::node()[not(self::书社:apply-attributes-to-root) and not(ancestor::*[not(self::书社:apply-attributes-to-root)])]"/>
                                <xslt:variable name="root-with-attributes">
                                        <xslt:choose>
-                                               <xslt:when test="$result-nodes/self::书社:*[local-name()='raw-text' or local-name()='base64-binary']|$result-nodes/@书社:disable-output-wrapping|exsl:node-set($书社:result)//书社:apply-attributes-to-root/@书社:disable-output-wrapping">
+                                               <xslt:when test="$result-nodes/self::书社:*[local-name()='raw-text' or local-name()='base64-binary' or local-name()='archive']|$result-nodes/@书社:disable-output-wrapping|exsl:node-set($书社: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="exsl:node-set($书社:result)//书社:apply-attributes-to-root"/>
@@ -265,7 +271,34 @@ If a copy of the M·P·L was not distributed with this file, You can obtain one
                                        <xslt:apply-templates select="@*|node()" mode="书社:application"/>
                                </xslt:copy>
                        </xslt:template>
-                       <xslt:template match="@书社:destination|@书社:disable-output-wrapping" mode="书社:application" priority="1"/>
+                       <xslt:template match="@书社:destination|@书社:disable-output-wrapping|@书社:archived-as[../ancestor::*[not(self::书社:apply-attributes-to-root or self::书社:apply-attributes)]]" mode="书社:application" priority="1"/>
+                       <xslt:template match="书社:archive" mode="书社:application">
+                               <xslt:copy>
+                                       <xslt:for-each select="@*|node()">
+                                               <xslt:choose>
+                                                       <xslt:when test="self::*">
+                                                               <xslt:variable name="component">
+                                                                       <xslt:choose>
+                                                                               <xslt:when test="self::书社:*[local-name()='raw-text' or local-name()='base64-binary' or local-name()='archive']|@书社:disable-output-wrapping">
+                                                                                       <xslt:copy-of select="."/>
+                                                                               </xslt:when>
+                                                                               <xslt:otherwise>
+                                                                                       <xslt:call-template name="书社:wrap">
+                                                                                               <xslt:with-param name="nodes" select="."/>
+                                                                                       </xslt:call-template>
+                                                                               </xslt:otherwise>
+                                                                       </xslt:choose>
+                                                               </xslt:variable>
+                                                               <xslt:apply-templates select="exsl:node-set($component)/node()" mode="书社:application"/>
+                                                       </xslt:when>
+                                                       <xslt:when test="../ancestor::*[not(self::书社:apply-attributes-to-root or self::书社:apply-attributes)] and local-name()='archived-as' and namespace-uri()='&书社;'"/>
+                                                       <xslt:otherwise>
+                                                               <xslt:apply-templates select="." mode="书社:application"/>
+                                                       </xslt:otherwise>
+                                               </xslt:choose>
+                                       </xslt:for-each>
+                               </xslt:copy>
+                       </xslt:template>
                        <xslt:template match="书社:apply-attributes" mode="书社:application" priority="1">
                                <xslt:variable name="children">
                                        <xslt:apply-templates select="node()" mode="书社:application"/>
This page took 0.030517 seconds and 4 git commands to generate.