Re: [xsl] inserting a child element while honoring the parent element's content model

Subject: Re: [xsl] inserting a child element while honoring the parent element's content model
From: "Chris Papademetrious christopher.papademetrious@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 25 Feb 2023 02:10:56 -0000
Here is an input document:


<?xml version="1.0" encoding="utf-8" ?>
<topic>
  <title>My Topic</title>
  <prolog>
    <author>chrispy</author>
  </prolog>
  <body><p>Hello!</p></body>
</topic>


and a stylesheet that defines some content models, then inserts some <keyword>
elements in the <topic>:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform
  xmlns:xs=http://www.w3.org/2001/XMLSchema
  xmlns:map=http://www.w3.org/2005/xpath-functions/map
  exclude-result-prefixes="#all"
  version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:output indent="yes"/>

  <!-- define some content models -->
  <xsl:variable name="content-models" as="map(xs:string, xs:string*)"
select="map {
    'topic': ('title', 'titlealts', 'shortdesc', 'abstract', 'prolog', 'body',
'related-links', 'topic'),
    'prolog': ('author', 'source', 'publisher', 'copyright', 'critdates',
'permissions', 'metadata', 'change-historylist', 'resourceid', 'data',
'sort-as', 'data-about', 'foreign', 'mathml', 'svg-container', 'unknown'),
    'metadata': ('audience', 'category', 'keywords', 'prodinfo', 'othermeta',
'data', 'sort-as', 'data-about', 'foreign', 'mathml', 'svg-container',
'unknown'),
    'keywords': ('indexterm', 'keyword')
  }"/>

  <!-- insert some <keyword> elements in a <topic> -->
  <xsl:template match="topic">
    <xsl:apply-templates select="." mode="insert-stuff">
      <xsl:with-param name="path" select="tokenize('prolog/metadata/keywords',
'/')" as="xs:string*"/>
      <xsl:with-param name="content" as="element()*" tunnel="yes">
        <keyword>new keyword 1</keyword>
        <keyword>new keyword 2</keyword>
      </xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>

  <!-- perform content-aware insertion on an element -->
  <xsl:template match="*" mode="insert-stuff">
    ...omitted...
  </xsl:template>

</xsl:stylesheet>


You'll need to insert the mode="insert-stuff" template where indicated; email
size restrictions did not allow everything in one email.

If you call the template with $path set to an empty sequence, then the content
is inserted directly in the current element.

-----
Chris Papademetrious
Tech Writer, Implementation Group
(610) 628-9718 home office
(570) 460-6078 cell

Current Thread