diff --git a/.gitignore b/.gitignore
index 536013518b..397b2f2bd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,212 +1,213 @@
 # Common
 \#*
 .\#*
 GPATH
 GRTAGS
 GTAGS
 TAGS
 Makefile
 Makefile.in
 .deps
 .dirstamp
 .libs
 *.pc
 *.pyc
 *.bz2
 *.tar.gz
 *.rpm
 *.la
 *.lo
 *.o
 *~
 *.gcda
 *.gcno
 
 
 # Autobuild
 aclocal.m4
 autoconf
 autoheader
 autom4te.cache/
 automake
 build.counter
 compile
 config.guess
 config.log
 config.status
 config.sub
 configure
 depcomp
 install-sh
 include/stamp-*
 libtool
 libtool.m4
 ltdl.m4
 libltdl
 ltmain.sh
 missing
 py-compile
 /m4/argz.m4
 /m4/ltargz.m4
 /m4/ltoptions.m4
 /m4/ltsugar.m4
 /m4/ltversion.m4
 /m4/lt~obsolete.m4
 test-driver
 ylwrap
 
 # Configure targets
 Doxyfile
 /cts/CTS.py
 /cts/CTSlab.py
 /cts/CTSvars.py
 /cts/LSBDummy
 /cts/OCFIPraTest.py
 /cts/benchmark/clubench
 /cts/cluster_test
 /cts/cts
 /cts/cts-cli
 /cts/cts-coverage
 /cts/cts-exec
 /cts/cts-fencing
 /cts/cts-log-watcher
 /cts/cts-regression
 /cts/cts-scheduler
 /cts/cts-support
 /cts/fence_dummy
 /cts/lxc_autogen.sh
 /cts/pacemaker-cts-dummyd
 /cts/pacemaker-cts-dummyd@.service
 /daemons/execd/pacemaker_remote
 /daemons/execd/pacemaker_remote.service
 /daemons/fenced/fence_legacy
 /daemons/pacemakerd/pacemaker
 /daemons/pacemakerd/pacemaker.combined.upstart
 /daemons/pacemakerd/pacemaker.service
 /daemons/pacemakerd/pacemaker.upstart
 /extra/logrotate/pacemaker
 /extra/resources/ClusterMon
 /extra/resources/HealthSMART
 /extra/resources/SysInfo
 /extra/resources/ifspeed
 /extra/resources/o2cb
 include/config.h
 include/config.h.in
 include/crm_config.h
 publican.cfg
 /tools/cibsecret
 /tools/crm_error
 /tools/crm_failcount
 /tools/crm_master
 /tools/crm_mon.service
 /tools/crm_mon.upstart
 /tools/crm_report
 /tools/crm_standby
 /tools/report.collector
 /tools/report.common
 
 # Build targets
 *.7
 *.7.xml
 *.7.html
 *.8
 *.8.xml
 *.8.html
 doc/*/en-US/images/*.png
 doc/*/tmp/**
 doc/*/publish
 /daemons/attrd/pacemaker-attrd
 /daemons/based/pacemaker-based
 /daemons/based/cibmon
 /daemons/controld/pacemaker-controld
 /daemons/execd/cts-exec-helper
 /daemons/execd/pacemaker-execd
 /daemons/execd/pacemaker-remoted
 /daemons/fenced/cts-fence-helper
 /daemons/fenced/pacemaker-fenced
 /daemons/fenced/pacemaker-fenced.xml
 /daemons/pacemakerd/pacemakerd
 /daemons/schedulerd/pacemaker-schedulerd
 /daemons/schedulerd/pacemaker-schedulerd.xml
 /daemons/schedulerd/ptest
 doc/api/*
 doc/Clusters_from_Scratch.txt
 doc/Pacemaker_Explained.txt
 doc/acls.html
 doc/crm_fencing.html
 doc/publican-catalog*
 scratch
 /tools/attrd_updater
 /tools/cibadmin
 /tools/crmadmin
 /tools/crm_attribute
 /tools/crm_diff
 /tools/crm_mon
 /tools/crm_node
 /tools/crm_resource
 /tools/crm_shadow
 /tools/crm_simulate
 /tools/crm_ticket
 /tools/crm_verify
 /tools/iso8601
 /tools/stonith_admin
 xml/crm.dtd
 xml/pacemaker*.rng
 xml/versions.rng
 doc/shared/en-US/*.xml
 doc/Clusters_from_Scratch.build
 doc/Clusters_from_Scratch/en-US/Ap-*.xml
 doc/Clusters_from_Scratch/en-US/Ch-*.xml
 doc/Pacemaker_Administration.build
 doc/Pacemaker_Administration/en-US/Ch-*.xml
 doc/Pacemaker_Development.build
 doc/Pacemaker_Development/en-US/Ch-*.xml
 doc/Pacemaker_Explained.build
 doc/Pacemaker_Explained/en-US/Ch-*.xml
 doc/Pacemaker_Explained/en-US/Ap-*.xml
 doc/Pacemaker_Remote.build
 doc/Pacemaker_Remote/en-US/Ch-*.xml
 lib/gnu/libgnu.a
 lib/gnu/stdalign.h
 *.coverity
 
 # Test detritus
 /cts/.regression.failed.diff
 /cts/scheduler/*.ref
 /cts/scheduler/*.up
 /cts/scheduler/*.up.err
 /cts/scheduler/bug-rh-1097457.log
 /cts/scheduler/bug-rh-1097457.trs
 /cts/scheduler/shadow.*
 /cts/test-suite.log
 /xml/test-2/*.up
 /xml/test-2/*.up.err
+/xml/assets/diffview.js
 
 # Formerly built files (helps when jumping back and forth in checkout)
 /attrd
 /cib
 /coverage.sh
 /crmd
 /cts/HBDummy
 /fencing
 /lrmd
 /mcp
 /pengine
 
 #Other 
 mock
 HTML
 pacemaker*.spec
 coverity-*
 
 compat_reports
 .ABI-build
 abi_dumps
 logs
 
 *.patch
 *.diff
 *.sed
 *.orig
 *.rej
 *.swp
diff --git a/xml/assets/upgrade-2.10-htmldiff.xsl b/xml/assets/upgrade-2.10-htmldiff.xsl
new file mode 100644
index 0000000000..22922904c6
--- /dev/null
+++ b/xml/assets/upgrade-2.10-htmldiff.xsl
@@ -0,0 +1,351 @@
+<!--
+ Copyright 2018 Red Hat, Inc.
+ Author: Jan Pokorny <jpokorny@redhat.com>
+ Part of pacemaker project
+ SPDX-License-Identifier: GPL-2.0-or-later
+ -->
+<xsl:stylesheet version="1.0"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:cibtr="http://clusterlabs.org/ns/pacemaker/cibtr-2"
+                xmlns:exsl="http://exslt.org/common">
+<!-- NOTE: this is an exception from rule forbidding EXSLT's usage -->
+
+<xsl:include href="../upgrade-2.10.xsl"/>
+
+<!--
+ we are embedding files from 3rd party project so as to reproduce the content
+ of XML into HTML-formatted presentation form; alternatively:
+ * from mozilla/firefox:
+   - view-source.xsl by Keith Visco (example transformation for transformiix)
+     https://dxr.mozilla.org/mozilla/source/extensions/transformiix/source/examples
+   - XMLPrettyPrint.xsl by Jonas Sicking
+     https://dxr.mozilla.org/mozilla-central/source/dom/xml/resources
+     https://hg.mozilla.org/mozilla-central/file/9b2a99adc05e/content/xml/document/resources/XMLPrettyPrint.xsl
+     or possibly its readily sanitized version from rdf-viewer project
+     https://github.com/marianafranco/rdf-viewer
+ * custom stylesheet to be written
+ -->
+<xsl:param name="highlight-namespace" select="''"/>
+<!--
+<xsl:include href="https://raw.githubusercontent.com/Boldewyn/view-source/master/library.xsl"/>
+<xsl:include href="https://raw.githubusercontent.com/Boldewyn/view-source/master/original.xsl"/>
+ -->
+<xsl:include href="view-source-library.xsl"/>
+<xsl:include href="view-source-original.xsl"/>
+
+<xsl:output method="xml" encoding="UTF-8"
+            omit-xml-declaration="yes"
+            doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+            doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/>
+
+<!-- B: identity mode -->
+<xsl:template match="@*|node()" mode="identity">
+  <xsl:copy>
+    <xsl:apply-templates select="@*|node()" mode="identity"/>
+  </xsl:copy>
+</xsl:template>
+
+<!-- used in test files to allow in-browser on-the-fly checking -->
+<xsl:template match="processing-instruction()[
+                       name() = 'xml-stylesheet'
+                       and
+                       count(..|/) = 1
+                     ]"
+              mode="identity"/>
+<!-- E: identity mode -->
+
+<xsl:template match="/">
+  <xsl:variable name="before-upgrade">
+    <xsl:apply-templates mode="identity"/>
+  </xsl:variable>
+
+  <xsl:variable name="after-upgrade">
+    <xsl:apply-templates mode="cibtr:main"/>
+  </xsl:variable>
+
+  <html>
+    <head>
+      <title>
+        <xsl:text>upgrade-2.10 on-the-fly in-browser transformation</xsl:text>
+      </title>
+      <style>
+        ol.count,.possibly-revealed { display: none; }
+        li.delete { color: red; }
+        li.delete em { background-color: #FFE4E1; }
+        li.insert { color: green; }
+        li.insert em { background-color: #FAFAD2; }
+        .count,.data { font-family: monospace;
+                       background-color: #F8F8FF;
+                       border: 1px solid #DCDCDC; }
+      </style>
+      <script type="text/javascript">
+        var global = { prettydiff: {} },  /* for diffview.js */
+            diffview_source = new String("../assets/diffview.js");
+
+        /* add location-based file detail to the title */
+        var split_url = document.URL.split('/'),
+            basename = new String(split_url[split_url.length - 1]),
+            /* see whether there's 'test-\d+' in URL as a discriminator */
+            is_test = split_url.some(function(item, index, array) {
+              if (index &lt; array.length - 1 &amp;&amp; item.match(/test-\d+/))
+                return true;
+              return false;
+            });
+
+        window.addEventListener("DOMContentLoaded", function(event) {
+          /* update title + headline */
+          var basename_title = new String(basename + " upgrade");
+          document.getElementById("headline").innerText = basename_title;
+          document.title = basename_title + " [" + document.title + "]";
+
+          /* add location-based file detail to the acknowledgement's text */
+          document.getElementById("acknowledgement")
+            .innerHTML = document.getElementById("acknowledgement").innerHTML
+                         .replace("@basename@", basename);
+
+          /* make expand/collapse buttons udner debugging section work */
+          document.querySelectorAll("#original, #transformed").forEach(
+            function(item) {
+              item.querySelector(".expand").addEventListener("click",
+                                                             function(event) {
+                item.querySelectorAll(".possibly-revealed").forEach(
+                  function(item) {
+                    item.classList.replace("possibly-revealed", "revealed");
+                  }
+                );
+                this.classList.add("possibly-revealed");
+                event.preventDefault();
+              });
+              item.querySelector(".collapse").addEventListener("click",
+                                                               function(event) {
+                item.querySelectorAll(".revealed").forEach(
+                  function(item) {
+                    item.classList.replace("revealed", "possibly-revealed");
+                  }
+                );
+                item.querySelector(".expand").classList.remove("possibly-revealed");
+                event.preventDefault();
+              });
+            }
+          );
+
+          if (is_test) {
+            var xhr1 = new XMLHttpRequest(),
+                xhr2 = new XMLHttpRequest(),
+                basename_split = basename.split('.');
+
+            /* fetch expected out-of-band messages */
+            xhr1.onload = function() {
+              document.getElementById("expected-messages").innerText = this.responseText;
+              document.querySelectorAll(["#expected-messages",
+                                         "#expected-messages-ext",
+                                         "#navigation"]).forEach(
+                function(item) {
+                  item.classList.remove("possibly-revealed");
+                }
+              );
+            };
+            xhr1.open("GET", basename_split.splice(0, basename_split.length - 1)
+                                           .join('.') + ".ref.err");
+            xhr1.responseType = "text";
+            xhr1.send();
+
+            /* fetch previous/next pointers */
+            xhr2.onload = function() {
+              var prev_link, next_link,
+                  found = false;
+              Array.prototype.every.call(
+                this.responseXML.getElementsByTagName("a"),
+                function(item) {
+                  if (item.href.endsWith(basename_split[basename_split.length - 1])) {
+                    if (item.href.endsWith(basename))
+                      found = true;
+                    else if (!found)
+                      prev_link = item;
+                    else if (next_link !== undefined)
+                      return false;
+                    else
+                      next_link = item;
+                  }
+                  return true;
+                }
+              );
+              if (prev_link !== undefined)
+                document.getElementById("navigation-prev").href = prev_link.href;
+              if (next_link !== undefined)
+              document.getElementById("navigation-next").href = next_link.href;
+            };
+            xhr2.open("GET", ".");
+            xhr2.responseType = "document";
+            xhr2.send();
+          }
+        });
+
+        window.addEventListener("load", function(event) {
+          /* trigger diff'ing */
+          document
+            .getElementById("output")
+            .innerHTML = global.prettydiff.diffview({
+              source: document.getElementById("original-placeholder").innerText,
+              sourcelabel: "Differences: original",
+              diff: document.getElementById("transformed-placeholder").innerText,
+              difflabel: "transformed (some whitespace stripped)",
+              diffview: "inline",
+              lang: "text"
+            })[0];
+
+          /* add proper location of diffview.js */
+          var diffview_link = document.getElementById("diffview-link");
+          if (diffview_link.host != document.location.host) {
+            diffview_link.href = diffview_source;
+            diffview_link.parentElement.querySelector(".possibly-revealed")
+              .classList.remove("possibly-revealed");
+            diffview_link.parentElement.querySelector(".revealed")
+              .classList.replace("revealed", "possibly-revealed");
+          }
+        });
+
+        /* bind left/right arrows */
+        window.addEventListener("keydown", function(event) {
+          switch (event.keyCode) {
+          case 37:
+            document.location = document.getElementById("navigation-prev").href;
+            break;
+          case 39:
+            document.location = document.getElementById("navigation-next").href;
+            break;
+          }
+        });
+      </script>
+      <script type="text/javascript" src="../assets/diffview.js"/>
+      <!-- fallback to externally fetched js, without any guarantees,
+           safety ones or otherwise -->
+      <script type="text/javascript">
+        if (typeof global.prettydiff.diffview == "undefined") {
+          diffview_source = new String("https://raw.githubusercontent.com/prettydiff/prettydiff/2.2.8/lib/diffview.js");
+          document.write(unescape('%3Cscript type="text/javascript" src=' + diffview_source + '/%3E'));
+        }
+      </script>
+    </head>
+    <body>
+      <h1 id="headline">test</h1>
+      <p>
+        <strong>Using <a href="../upgrade-2.10.xsl">upgrade-2.10</a> on-the-fly in-browser transformation</strong>
+        <span id="navigation" class="possibly-revealed">
+          [
+          <a id="navigation-prev" href="#">previous</a>
+          and
+          <a id="navigation-next" href="#">next</a>, or use arrows
+          ]
+        </span>
+      </p>
+      <p id="output">
+        Differences highlight view to be loaded here.
+      </p>
+      <h3>Diagnostics</h3>
+      <p>
+        Open <a href="https://webmasters.stackexchange.com/a/77337">JS console</a>
+        (e.g. <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>J</kbd>, focusing JS + log combo)
+        <span id="expected-messages-ext" class="possibly-revealed">
+          to check the actual messages from the in-browser transformation match the baseline:
+        </span>
+      </p>
+      <pre id="expected-messages" class="data possibly-revealed">
+        Expected diagnostic messages to be loaded here.
+      </pre>
+      <h3>Debugging</h3>
+      <p>
+        These are raw data (beware, already chewed with the
+        <a href="../assets/view-source-original.xsl">view-source</a>
+        transformation, hence not very suitable for copying) entering
+        the differential generating processs:
+      </p>
+      <p id="original">
+        <span>
+          <a class="expand" href="">original+</a>
+          <a class="collapse possibly-revealed" href="">original-</a>
+        </span>
+        <br/>
+        <pre id="original-placeholder" class="data possibly-revealed">
+          <xsl:apply-templates select="exsl:node-set($before-upgrade)/node()" mode="original"/>
+        </pre>
+      </p>
+      <p id="transformed">
+        <span>
+          <a class="expand" href="">transformed+</a>
+          <a class="collapse possibly-revealed" href="">transformed-</a>
+        </span>
+        <br/>
+        <pre id="transformed-placeholder" class="data possibly-revealed">
+          <xsl:apply-templates select="exsl:node-set($after-upgrade)/node()" mode="original"/>
+        </pre>
+      </p>
+      <hr/>
+      <p id="acknowledgement">
+        This generated page is based on the externally provided pacemaker XML
+        configuration file (CIB), <span class="data">@basename@</span>, which is
+        the primary object of interest here.
+        But the rendered page wouldn't be possible without the actual
+        transformations and other auxiliary files that come with these notices:
+        <br/>
+        <ul>
+          <li id="ack-diffview">
+            <a href="../assets/diffview.js" id="diffview-link">diffview.js</a>
+            <p class="data revealed">
+              This file was obtained from <a href="https://github.com/prettydiff/prettydiff">prettydiff/prettydiff</a> project:<br/>
+              <a href="https://raw.githubusercontent.com/prettydiff/prettydiff/2.2.8/lib/diffview.js">diffview.js</a><br/>
+              <br/>
+              Licensing governed with:<br/>
+              <a href="https://github.com/prettydiff/prettydiff/blob/2.2.8/license.txt">license.txt</a><br/>
+              <br/>
+              > Rights holder Austin Cheney and Pretty Diff<br/>
+              > <br/>
+              > Pretty Diff project, as of version 2.1.17 and all following versions<br/>
+              > unless otherwise changed, is licensed with a Creative Commons 1.0<br/>
+              > Universal license (CC0).
+            </p>
+            <p class="data possibly-revealed">
+              This file is being served directly from <a href="https://raw.githubusercontent.com/prettydiff/prettydiff/2.2.8/lib/diffview.js">
+              GitHub hosted location</a>, hence refer to <a href="https://raw.githubusercontent.com/prettydiff/prettydiff/2.2.8">
+              respective repo tree</a>
+            </p>
+          </li>
+          <li id="ack-view-source">
+            <a href="../assets/view-source-library.xsl">library.xsl</a>
+            and
+            <a href="../assets/view-source-original.xsl">original.xsl</a>
+            <p class="data">
+              This file was obtained from <a href="https://github.com/Boldewyn/view-source">Boldewyn/view-source</a> project:<br/>
+              <a href="https://raw.githubusercontent.com/Boldewyn/view-source/f425605366b9f5a52e6a71632785d6e4543c705e/library.xsl">library.xsl</a><br/>
+              <a href="https://raw.githubusercontent.com/Boldewyn/view-source/f425605366b9f5a52e6a71632785d6e4543c705e/original.xsl">original.xsl</a><br/>
+              <br/>
+              Licensing governed with:<br/>
+              <a href="https://github.com/Boldewyn/view-source/blob/f425605366b9f5a52e6a71632785d6e4543c705e/README">README</a><br/>
+              <br/>
+              > The stylesheet is published under an MIT-style license and the GPL v2.<br/>
+              > Choose at your liking.
+            </p>
+          </li>
+          <li id="ack-upgrade">
+            <a href="../assets/upgrade-2.10-htmldiff.xsl">upgrade-2.10-htmldiff.xsl</a>
+            (master template for this report) and
+            <a href="../upgrade-2.10.xsl">upgrade-2.10.xsl</a>
+            (actual upgrade engine)
+            <p class="data">
+              Copyright 2018 <a href="https://redhat.com">Red Hat, Inc.</a><br/>
+              Author: <a href="https://wiki.clusterlabs.org/wiki/User:Jpokorny">Jan Pokorny</a>
+              &lt;<a href="mailto:jpokorny@redhat.com">jpokorny@redhat.com</a>&gt;<br/>
+              <a href="https://github.com/ClusterLabs/pacemaker/tree/master/xml">Part</a> of
+              <a href="https://wiki.clusterlabs.org/wiki/Pacemaker">pacemaker</a> project<br/>
+              <a href="https://spdx.org/sites/cpstandard/files/pages/files/using_spdx_license_list_short_identifiers.pdf#page=5">SPDX-License-Identifier</a>:
+              <a href="https://spdx.org/licenses/GPL-2.0-or-later.html">GPL-2.0-or-later</a>
+            </p>
+          </li>
+        </ul>
+      </p>
+    </body>
+  </html>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/xml/assets/view-source-library.xsl b/xml/assets/view-source-library.xsl
new file mode 100644
index 0000000000..8ac0dc2fa7
--- /dev/null
+++ b/xml/assets/view-source-library.xsl
@@ -0,0 +1,222 @@
+<?xml version="1.0" ?>
+<!--
+ This file was obtained from https://github.com/Boldewyn/view-source project:
+ https://raw.githubusercontent.com/Boldewyn/view-source/f425605366b9f5a52e6a71632785d6e4543c705e/library.xsl
+
+ Licensing governed with:
+ https://github.com/Boldewyn/view-source/blob/f425605366b9f5a52e6a71632785d6e4543c705e/README
+
+ > The stylesheet is published under an MIT-style license and the GPL v2.
+ > Choose at your liking.
+
+ -->
+<t:stylesheet version="1.0"
+  xmlns:t="http://www.w3.org/1999/XSL/Transform"
+  xmlns="http://www.w3.org/1999/xhtml">
+
+  <t:variable name="ns" xmlns="">
+    <empty></empty>
+    <xml>http://www.w3.org/XML/1998/namespace</xml>
+    <xmlns>http://www.w3.org/2000/xmlns/</xmlns>
+    <xhtml>http://www.w3.org/1999/xhtml</xhtml>
+    <svg>http://www.w3.org/2000/svg</svg>
+    <mathml>http://www.w3.org/1998/Math/MathML</mathml>
+    <xslt>http://www.w3.org/1999/XSL/Transform</xslt>
+    <fo>http://www.w3.org/1999/XSL/Format</fo>
+    <smil>http://www.w3.org/2005/SMIL21/Language</smil>
+    <xlink>http://www.w3.org/1999/xlink</xlink>
+    <xsd>http://www.w3.org/2001/XMLSchema</xsd>
+    <xsd-inst>http://www.w3.org/2001/XMLSchema-instance</xsd-inst>
+    <xforms>http://www.w3.org/2001/xforms</xforms>
+    <xinclude>http://www.w3.org/2001/XInclude</xinclude>
+    <xul>http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul</xul>
+    <rdf>http://www.w3.org/1999/02/22-rdf-syntax-ns#</rdf>
+  </t:variable>
+
+  <!--
+    format text, so that newlines get indented correctly
+  -->
+  <t:template name="format-text">
+    <t:param name="text" select="." />
+    <t:param name="indent" />
+    <t:choose>
+      <t:when test="contains($text, '&#xA;')">
+        <t:value-of select="normalize-space(substring-before($text, '&#xA;'))" />
+        <t:text>&#xA;</t:text>
+        <t:value-of select="$indent" />
+        <t:call-template name="format-text">
+          <t:with-param name="text" select="substring-after($text, '&#xA;')" />
+          <t:with-param name="indent" select="$indent " />
+        </t:call-template>
+      </t:when>
+      <t:otherwise>
+        <t:value-of select="normalize-space($text)" />
+      </t:otherwise>
+    </t:choose>
+  </t:template>
+
+  <!--
+    HTML entity quote stuff
+  -->
+  <t:template name="quote">
+    <t:param name="text" />
+    <t:call-template name="replace">
+      <t:with-param name="text">
+        <t:call-template name="replace">
+          <t:with-param name="text">
+            <t:call-template name="replace">
+              <t:with-param name="text">
+                <t:call-template name="replace">
+                  <t:with-param name="text">
+                    <t:call-template name="replace">
+                      <t:with-param name="text">
+                        <t:value-of select="$text" />
+                      </t:with-param>
+                      <t:with-param name="from" select="'&amp;'" />
+                      <t:with-param name="to" select="'&amp;amp;'" />
+                    </t:call-template>
+                  </t:with-param>
+                  <t:with-param name="from" select='"&apos;"' />
+                  <t:with-param name="to" select="'&amp;apos;'" />
+                </t:call-template>
+              </t:with-param>
+              <t:with-param name="from" select="'&quot;'" />
+              <t:with-param name="to" select="'&amp;quot;'" />
+            </t:call-template>
+          </t:with-param>
+          <t:with-param name="from" select="'&gt;'" />
+          <t:with-param name="to" select="'&amp;gt;'" />
+        </t:call-template>
+      </t:with-param>
+      <t:with-param name="from" select="'&lt;'" />
+      <t:with-param name="to" select="'&amp;lt;'" />
+    </t:call-template>
+  </t:template>
+
+  <!--
+    replace a string with another
+  -->
+  <t:template name="replace">
+    <t:param name="text" />
+    <t:param name="from" />
+    <t:param name="to" />
+    <t:choose>
+      <t:when test="not($from)">
+        <t:value-of select="$text" />
+      </t:when>
+      <t:when test="contains($text, $from)">
+        <t:value-of select="substring-before($text, $from)" />
+        <t:value-of select="$to" />
+        <t:call-template name="replace">
+          <t:with-param name="text" select="substring-after($text, $from)" />
+          <t:with-param name="from" select="$from" />
+          <t:with-param name="to" select="$to" />
+        </t:call-template>
+      </t:when>
+      <t:otherwise>
+        <t:value-of select="$text" />
+      </t:otherwise>
+    </t:choose>
+  </t:template>
+
+  <!--
+    parse the value of an attribute (find links and make them clickable)
+  -->
+  <t:template name="parse-attval">
+    <t:param name="att" select="." />
+    <t:choose>
+      <!-- FIXME: element{xhtml} / @attr{obscure-ns} 'href' gets linkified -->
+      <t:when test="(namespace-uri($att/..) = document('')//t:variable[@name = 'ns']/xml/text()   and ( local-name($att) = 'base' )) or
+                    (namespace-uri($att/..) = document('')//t:variable[@name = 'ns']/xhtml/text() and ( local-name($att) = 'src' or local-name($att) = 'href' )) or
+                    (namespace-uri($att/..) = document('')//t:variable[@name = 'ns']/svg/text()   and ( local-name($att) = 'src' )) or
+                    (namespace-uri($att/..) = document('')//t:variable[@name = 'ns']/xslt/text()  and ( local-name($att) = 'href' )) or
+                    (namespace-uri($att/..) = document('')//t:variable[@name = 'ns']/smil/text()  and ( local-name($att) = 'src' or local-name($att) = 'href' )) or
+                    (namespace-uri($att)    = document('')//t:variable[@name = 'ns']/xlink/text() and ( local-name($att) = 'href' or local-name($att) = 'role' )) or
+                    contains(substring($att, 1, 7), 'http://') or
+                    contains(substring($att, 1, 8), 'https://') or
+                    contains(substring($att, 1, 7), 'file://') or
+                    contains(substring($att, 1, 7), 'mailto:') or
+                    contains(substring($att, 1, 6), 'ftp://') or
+                    contains(substring($att, 1, 7), 'ftps://') or
+                    contains(substring($att, 1, 5), 'news:') or
+                    contains(substring($att, 1, 4), 'urn:') or
+                    contains(substring($att, 1, 5), 'ldap:') or
+                    contains(substring($att, 1, 5), 'data:')">
+        <a>
+          <t:attribute name="href">
+            <t:value-of select="$att" />
+          </t:attribute>
+          <t:call-template name="quote">
+            <t:with-param name="text" select="$att" />
+          </t:call-template>
+        </a>
+      </t:when>
+      <t:otherwise>
+        <t:call-template name="quote">
+          <t:with-param name="text" select="$att" />
+        </t:call-template>
+      </t:otherwise>
+    </t:choose>
+  </t:template>
+
+  <!--
+    print the name of a node plus the namespace URI in a title attribute
+  -->
+  <t:template name="print-name">
+    <t:param name="node" select="." />
+    <span class="label">
+      <t:if test="namespace-uri($node)">
+        <t:attribute name="title">
+          <t:value-of select="namespace-uri($node)" />
+        </t:attribute>
+      </t:if>
+      <t:choose>
+        <t:when test="name($node) != local-name($node)">
+          <span class="nsprefix">
+            <t:value-of select="substring-before(name($node), ':')" />
+          </span>
+          <span class="nscolon syntax">
+            <t:text>:</t:text>
+          </span>
+          <span class="local-name">
+            <t:value-of select="local-name($node)" />
+          </span>
+        </t:when>
+        <t:otherwise>
+          <t:value-of select="name($node)" />
+        </t:otherwise>
+      </t:choose>
+    </span>
+  </t:template>
+
+  <!--
+    check the used language against a list of known ones
+  -->
+  <t:template name="detect-lang">
+    <t:param name="node" select="." />
+    <t:if test="namespace-uri($node) = $highlight-namespace">
+      <t:text>highlight </t:text>
+    </t:if>
+    <t:value-of select="local-name(document('')//t:variable[@name = 'ns']/*[text() = namespace-uri($node)])" />
+  </t:template>
+
+  <t:key name="kElemByNSURI"
+       match="*[namespace::*[not(. = ../../namespace::*)]]"
+       use="namespace::*[not(. = ../../namespace::*)]" />
+
+  <!--
+    get a list of all namespaces used in the document
+  -->
+  <t:template name="get-namespace-nodes">
+    <script type="text/javascript">
+      var namespaces = [
+      <t:for-each select="//namespace::*[not(. = ../../namespace::*)]
+                        [count(..|key('kElemByNSURI',.)[1])=1]">
+        <t:value-of select="concat('&quot;',.,'&quot;,')"/>
+      </t:for-each>
+      'DUMMY'
+      ];
+    </script>
+  </t:template>
+
+</t:stylesheet>
diff --git a/xml/assets/view-source-original.xsl b/xml/assets/view-source-original.xsl
new file mode 100644
index 0000000000..327e0d38bc
--- /dev/null
+++ b/xml/assets/view-source-original.xsl
@@ -0,0 +1,103 @@
+<?xml version="1.0" ?>
+<!--
+ This file was obtained from https://github.com/Boldewyn/view-source project:
+ https://raw.githubusercontent.com/Boldewyn/view-source/f425605366b9f5a52e6a71632785d6e4543c705e/original.xsl
+
+ Licensing governed with:
+ https://github.com/Boldewyn/view-source/blob/f425605366b9f5a52e6a71632785d6e4543c705e/README
+
+ > The stylesheet is published under an MIT-style license and the GPL v2.
+ > Choose at your liking.
+
+ -->
+<t:stylesheet version="1.0"
+  xmlns:t="http://www.w3.org/1999/XSL/Transform"
+  xmlns="http://www.w3.org/1999/xhtml">
+
+  <!-- Elements (original) -->
+  <t:template match="*" mode="original">
+    <t:variable name="lang">
+      <t:call-template name="detect-lang" />
+    </t:variable>
+    <t:choose>
+      <t:when test="node()">
+        <span class="{$lang} element">
+          <span class="tag start">
+            <t:text>&lt;</t:text>
+            <t:call-template name="print-name" />
+            <t:for-each select="@*">
+              <t:apply-templates select="." mode="original" />
+            </t:for-each>
+            <t:text>&gt;</t:text>
+          </span>
+          <t:apply-templates mode="original" />
+          <span class="tag end">
+            <t:text>&lt;/</t:text>
+            <t:value-of select="name(.)"/>
+            <t:text>&gt;</t:text>
+          </span>
+        </span>
+      </t:when>
+      <t:otherwise>
+        <span class="{$lang} element empty">
+          <span class="tag empty">
+            <t:text>&lt;</t:text>
+            <t:call-template name="print-name" />
+            <t:for-each select="@*">
+              <t:apply-templates select="." mode="original" />
+            </t:for-each>
+            <t:text> /&gt;</t:text>
+          </span>
+        </span>
+      </t:otherwise>
+    </t:choose>
+  </t:template>
+
+  <!-- Attributes (original) -->
+  <t:template match="@*" mode="original">
+    <t:variable name="lang">
+      <t:call-template name="detect-lang" />
+    </t:variable>
+    <t:text> </t:text>
+    <span class="{$lang} attribute">
+      <t:call-template name="print-name" />
+      <t:text>="</t:text>
+      <span class="attribute-value">
+        <t:call-template name="parse-attval" />
+      </span>
+      <t:text>"</t:text>
+    </span>
+  </t:template>
+
+  <!-- Processing Instructions (original) -->
+  <t:template match="processing-instruction()" mode="original">
+    <span class="processing-instruction">
+      <t:text>&lt;?</t:text>
+      <t:value-of select="name(.)" />
+      <t:text> </t:text>
+      <t:value-of select="." />
+      <t:text>?&gt;</t:text>
+    </span>
+  </t:template>
+
+  <!-- Comments (original) -->
+  <t:template match="comment()" mode="original">
+    <span class="comment">
+      <t:text>&lt;!--</t:text>
+      <t:call-template name="quote">
+        <t:with-param name="text" select="." />
+      </t:call-template>
+      <t:text>--></t:text>
+    </span>
+  </t:template>
+
+  <!-- Text (original) -->
+  <t:template match="text()" mode="original">
+    <span class="text">
+      <t:call-template name="quote">
+        <t:with-param name="text" select="." />
+      </t:call-template>
+    </span>
+  </t:template>
+
+</t:stylesheet>
diff --git a/xml/regression.sh b/xml/regression.sh
index 806dce58a8..c3bce333c2 100755
--- a/xml/regression.sh
+++ b/xml/regression.sh
@@ -1,635 +1,640 @@
 #!/bin/sh
 # Copyright 2018 Red Hat, Inc.
 # Author: Jan Pokorny <jpokorny@redhat.com>
 # Part of pacemaker project
 # SPDX-License-Identifier: GPL-2.0-or-later
 
 set -eu
 test -d assets && test -d test-2 \
   || { echo 'Run me from source-tree-like location'; exit 1; }
 # $1=reference (can be '-' for stdin), $2=investigated
 # alt.: wdiff, colordiff, ...
 DIFF=${DIFF:-diff}
 DIFFOPTS=${DIFFOPTS--u}
 DIFFPAGER=${DIFFPAGER:-less -LRX}
 # $1=schema, $2=validated
 # alt.: jing -i
 RNGVALIDATOR=${RNGVALIDATOR:-xmllint --noout --relaxng}
 # $1=stylesheet, $2=source
 # alt.: Xalan, saxon, sabcmd/Sablotron (note: only validates reliably with -B)
 _xalan_wrapper() {
 	{ ${_XSLTPROCESSOR} "$2" "$1" 2>&1 >&3 \
 	  | sed -e '/^Source tree node.*$/d' \
 	        -e 's|^XSLT message: \(.*\) (Occurred.*)|\1|'; } 3>&- 3>&1 >&2
 }
 # Sablotron doesn't translate '-' file specification to stdin
 # and limits the length of the output message
 _sabcmd_wrapper() {
 	_sabw_sheet=${1:?}
 	_sabw_source=${2:?}
 	test "${_sabw_sheet}" != - || _sabw_sheet=/dev/stdin
 	test "${_sabw_source}" != - || _sabw_source=/dev/stdin
 	{ ${_XSLTPROCESSOR} "${_sabw_sheet}" "${_sabw_source}" 2>&1 >&3 \
 	  | sed -e '/^Warning \[code:89\]/d' \
 	        -e 's|^  xsl:message (\(.*\))$|\1|'; } 3>&- 3>&1 >&2
 }
 # filtered out message: https://bugzilla.redhat.com/show_bug.cgi?id=1577367
 _saxon_wrapper() {
 	{ ${_XSLTPROCESSOR} "-xsl:$1" "-s:$2" -versionmsg:off 2>&1 >&3 \
 	  | sed -e '/^Cannot find CatalogManager.properties$/d'; } 3>&- 3>&1 >&2
 }
 XSLTPROCESSOR=${XSLTPROCESSOR:-xsltproc --nonet}
 _XSLTPROCESSOR=${XSLTPROCESSOR}
 case "${XSLTPROCESSOR}" in
 [Xx]alan*|*/[Xx]alan*) XSLTPROCESSOR=_xalan_wrapper;;
 sabcmd*|*/sabcmd*)     XSLTPROCESSOR=_sabcmd_wrapper;;
 saxon*|*/saxon*)       XSLTPROCESSOR=_saxon_wrapper;;
 esac
 HTTPPORT=${HTTPPORT:-8000}  # Python's default
 WEBBROWSER=${WEBBROWSER:-firefox}
 
 tests=  # test* names (should go first) here will become preselected default
 
 #
 # commons
 #
 
 emit_result() {
 	_er_howmany=${1:?}  # how many errors (0/anything else incl. strings)
 	_er_subject=${2:?}
 	_er_prefix=${3-}
 
 	test -z "${_er_prefix}" || _er_prefix="${_er_prefix}: "
 
 	if test "${_er_howmany}" = 0; then
 		printf "%s%s finished OK\n" "${_er_prefix}" "${_er_subject}"
 	else
 		printf "%s%s encountered ${_er_howmany} errors\n" \
 		       "${_er_prefix}" "${_er_subject}"
 	fi
 }
 
 emit_error() {
 	_ee_msg=${1:?}
 	printf "%s\n" "${_ee_msg}" >&2
 }
 
 # returns 1 + floor of base 2 logaritm for _lo0r_i in 1...255,
 # or 0 for _lo0r_i = 0
 log2_or_0_return() {
 	_lo0r_i=${1:?}
 	return $(((!(_lo0r_i >> 1) && _lo0r_i) * 1 \
                 + (!(_lo0r_i >> 2) && _lo0r_i & (1 << 1)) * 2 \
                 + (!(_lo0r_i >> 3) && _lo0r_i & (1 << 2)) * 3 \
                 + (!(_lo0r_i >> 4) && _lo0r_i & (1 << 3)) * 4 \
                 + (!(_lo0r_i >> 5) && _lo0r_i & (1 << 4)) * 5 \
                 + (!(_lo0r_i >> 6) && _lo0r_i & (1 << 5)) * 6 \
                 + (!(_lo0r_i >> 7) && _lo0r_i & (1 << 6)) * 7 \
                 + !!(_lo0r_i >> 7) * 7 ))
 }
 
 # rough addition of two base 2 logarithms
 log2_or_0_add() {
 	_lo0a_op1=${1:?}
 	_lo0a_op2=${2:?}
 
 	if test ${_lo0a_op1} -gt ${_lo0a_op2}; then
 		return ${_lo0a_op1}
 	elif test ${_lo0a_op2} -gt ${_lo0a_op1}; then
 		return ${_lo0a_op2}
 	elif test ${_lo0a_op1} -gt 0; then
 		return $((_lo0a_op1 + 1))
 	else
 		return ${_lo0a_op1}
 	fi
 }
 
 #
 # test phases
 #
 
 # stdin: input file per line
 test_browser() {
 	_tb_cleanref=0
 	_tb_serverpid=
 
 	if ! read _tb_first; then
 		return 1
 	fi
 	cat >/dev/null 2>/dev/null  # read out the rest
 
 	test -f assets/diffview.js \
 	  || curl -Lo assets/diffview.js \
 	     'https://raw.githubusercontent.com/prettydiff/prettydiff/2.2.8/lib/diffview.js'
 
-	which python3 >/dev/null 2>/dev/null \
+	{ which python3 >/dev/null 2>/dev/null \
 	  && { python3 -m http.server "${HTTPPORT}" -b 127.0.0.1 \
-	       || emit_error "Python3 HTTP server shutdown/fail"; } \
-	  || { printf '%s %s\n' \
-	         'Python 2 backed HTTP server cannot listen at particular' \
-		 'address, discretion regarding firewall rules recommended!'
-	       python2 -m SimpleHTTPServer "${HTTPPORT}" \
-	       || emit_error "Python2 HTTP server shutdown/fail"; } &
+	       || emit_error "Python3 HTTP server fail"; return; } \
+	  || which python2 >/dev/null 2>/dev/null \
+	       && { printf '%s %s\n' \
+	            'Python 2 backed HTTP server cannot listen at particular' \
+	            'address, discretion regarding firewall rules recommended!'
+	            python2 -m SimpleHTTPServer "${HTTPPORT}" \
+	            || emit_error 'Python2 HTTP server fail'; return; } \
+	       || emit_error 'Cannot run Python based HTTP server' ; } &
 	_tb_serverpid=$!
 	${WEBBROWSER} "http://localhost:${HTTPPORT}/${_tb_first}" &
 	printf "When finished, just press Ctrl+C or kill %d, please\n" \
 	       "${_tb_serverpid}"
 	wait
 }
 
 # -r ... whether to remove referential files as well
 # stdin: input file per line
 test_cleaner() {
 	_tc_cleanref=0
 
 	while test $# -gt 0; do
 		case "$1" in
 		-r) _tc_cleanref=1;;
 		esac
 		shift
 	done
 
 	while read _tc_origin; do
 		_tc_origin=${_tc_origin%.*}
 		rm -f "${_tc_origin}.up" "${_tc_origin}.up.err"
 		rm -f "$(dirname "${_tc_origin}")/.$(basename "${_tc_origin}").up"
 		test ${_tc_cleanref} -eq 0 \
 		  || rm -f "${_tc_origin}.ref" "${_tc_origin}.ref.err"
 	done
 }
 
 test_selfcheck() {
 	_tsc_ret=0
 	_tsc_template=
 	_tsc_validator=
 
 	while test $# -gt 0; do
 		case "$1" in
 		-o=*) _tsc_template="${1#-o=}";;
 		esac
 		shift
 	done
 	_tsc_validator="${_tsc_template:?}"
 	_tsc_validator="cibtr-${_tsc_validator%%.*}.rng"
 	_tsc_template="upgrade-${_tsc_template}.xsl"
 
 	# check schema (sub-grammar) for custom transformation mapping alone
 	if ! ${RNGVALIDATOR} 'http://relaxng.org/relaxng.rng' "${_tsc_validator}"; then
 		_tsc_ret=$((_tsc_ret + 1))
 	fi
 	# check the overall XSLT per the main grammar + said sub-grammar
 	if ! ${RNGVALIDATOR} "xslt_${_tsc_validator}" "${_tsc_template}"; then
 		_tsc_ret=$((_tsc_ret + 1))
 	fi
 
 	log2_or_0_return ${_tsc_ret}
 }
 
 test_explanation() {
 	_tsc_template=
 
 	while test $# -gt 0; do
 		case "$1" in
 		-o=*) _tsc_template="upgrade-${1#-o=}.xsl";;
 		esac
 		shift
 	done
 
 	${XSLTPROCESSOR} upgrade-detail.xsl "${_tsc_template}"
 }
 
 # stdout: filename of the transformed file
 test_runner_upgrade() {
 	_tru_template=${1:?}
 	_tru_source=${2:?}  # filename
 	_tru_mode=${3:?}  # extra modes wrt. "referential" outcome, see below
 
 	_tru_ref="${_tru_source%.*}.ref"
         { test "$((_tru_mode & (1 << 0)))" -ne 0 \
 	  || test -f "${_tru_ref}.err"; } \
 	  && _tru_ref_err="${_tru_ref}.err" || _tru_ref_err=/dev/null
 	_tru_target="${_tru_source%.*}.up"
 	_tru_target_err="${_tru_target}.err"
 
 	if test $((_tru_mode & (1 << 2))) -eq 0; then
 		${XSLTPROCESSOR} "${_tru_template}" "${_tru_source}" \
 		  > "${_tru_target}" 2> "${_tru_target_err}" \
 		  || { _tru_ref=$?; echo "${_tru_target_err}"
 		       return ${_tru_ref}; }
 	else
 		# when -B (deblanked outcomes handling) requested, we:
 		# - drop blanks from the source XML
 		#   (effectively emulating pacemaker handling)
 		# - re-drop blanks from the XSLT outcome,
 		#   which is compared with referential outcome
 		#   processed with even greedier custom deblanking
 		#   (extraneous inter-element whitespace like blank
 		#   lines will not get removed otherwise, see lower)
 		xmllint --noblanks "${_tru_source}" \
 		  | ${XSLTPROCESSOR} "${_tru_template}" - \
 		  > "${_tru_target}" 2> "${_tru_target_err}" \
 		  || { _tru_ref=$?; echo "${_tru_target_err}"
 		       return ${_tru_ref}; }
 		# reusing variable no longer needed
 		_tru_template="$(dirname "${_tru_target}")"
 		_tru_template="${_tru_template}/.$(basename "${_tru_target}")"
 		mv "${_tru_target}" "${_tru_template}"
 		${XSLTPROCESSOR} - "${_tru_template}" > "${_tru_target}" <<-EOF
 	<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 	<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
 	<xsl:template match="@*|*|comment()|processing-instruction()">
 	  <xsl:copy>
 	    <xsl:apply-templates select="@*|node()"/>
 	  </xsl:copy>
 	</xsl:template>
 	<xsl:template match="text()">
 	  <xsl:value-of select="normalize-space(.)"/>
 	</xsl:template>
 	</xsl:stylesheet>
 EOF
 	fi
 
 	# only respond with the flags except for "-B", i.e., when both:
 	# - _tru_mode non-zero
 	# - "-B" in _tru_mode is zero (hence non-zero when flipped with XOR)
 	if test "$((_tru_mode * ((_tru_mode ^ (1 << 2)) & (1 << 2))))" -ne 0; then
 		if test $((_tru_mode & (1 << 0))) -ne 0; then
 			cp -a "${_tru_target}" "${_tru_ref}"
 			cp -a "${_tru_target_err}" "${_tru_ref_err}"
 		fi
 		if test $((_tru_mode & (1 << 1))) -ne 0; then
 			"${DIFF}" ${DIFFOPTS} "${_tru_source}" "${_tru_ref}" \
 			  | ${DIFFPAGER} >&2
 			if test $? -ne 0; then
 				printf "\npager failure\n" >&2
 				return 1
 			fi
 			printf '\nIs comparison OK? ' >&2
 			if read _tru_answer </dev/tty; then
 				case "${_tru_answer}" in
 				y|yes) ;;
 				*) echo "Answer not 'y' nor 'yes'" >&2; return 1;;
 				esac
 			else
 				return 1
 			fi
 		fi
 	elif test -f "${_tru_ref}" && test -e "${_tru_ref_err}"; then
 		{ test "$((_tru_mode & (1 << 2)))" -eq 0 && cat "${_tru_ref}" \
 		    || ${XSLTPROCESSOR} - "${_tru_ref}" <<-EOF
 	<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 	<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
 	<xsl:template match="@*|*|comment()|processing-instruction()">
 	  <xsl:copy>
 	    <xsl:apply-templates select="@*|node()"/>
 	  </xsl:copy>
 	</xsl:template>
 	<xsl:template match="text()">
 	  <xsl:value-of select="normalize-space(.)"/>
 	</xsl:template>
 	</xsl:stylesheet>
 EOF
 		} \
 		  | "${DIFF}" ${DIFFOPTS} - "${_tru_target}" >&2 \
 		  && "${DIFF}" ${DIFFOPTS} "${_tru_ref_err}" \
 		       "${_tru_target_err}" >&2
 		if test $? -ne 0; then
 			emit_error "Outputs differ from referential ones"
 			echo "/dev/null"
 			return 1
 		fi
 	else
 		emit_error "Referential file(s) missing: ${_tru_ref}"
 		echo "/dev/null"
 		return 1
 	fi
 
 	echo "${_tru_target}"
 }
 
 test_runner_validate() {
 	_trv_schema=${1:?}
 	_trv_target=${2:?}  # filename
 
 	if ! ${RNGVALIDATOR} "${_trv_schema}" "${_trv_target}" \
 	    2>/dev/null; then
 		${RNGVALIDATOR} "${_trv_schema}" "${_trv_target}"
 	fi
 }
 
 # -o= ... which conventional version to deem as the transform origin
 # -t= ... which conventional version to deem as the transform target
 # -B
 # -D
 # -G ... see usage
 # stdin: input file per line
 test_runner() {
 	_tr_mode=0
 	_tr_ret=0
 	_tr_schema_o=
 	_tr_schema_t=
 	_tr_target=
 	_tr_template=
 
 	while test $# -gt 0; do
 		case "$1" in
 		-o=*) _tr_template="upgrade-${1#-o=}.xsl"
 		      _tr_schema_o="pacemaker-${1#-o=}.rng";;
 		-t=*) _tr_schema_t="pacemaker-${1#-t=}.rng";;
 		-G) _tr_mode=$((_tr_mode | (1 << 0)));;
 		-D) _tr_mode=$((_tr_mode | (1 << 1)));;
 		-B) _tr_mode=$((_tr_mode | (1 << 2)));;
 		esac
 		shift
 	done
 
 	if ! test -f "${_tr_schema_o:?}" || ! test -f "${_tr_schema_t:?}"; then
 		emit_error "Origin and/or target schema missing, rerun make"
 		return 1
 	fi
 
 	while read _tr_origin; do
 		printf '%-60s' "${_tr_origin}... "
 
 		# pre-validate
 		if ! test_runner_validate "${_tr_schema_o}" "${_tr_origin}"; then
 			_tr_ret=$((_tr_ret + 1)); echo "E:pre-validate"; continue
 		fi
 
 		# upgrade
 		if ! _tr_target=$(test_runner_upgrade "${_tr_template}" \
 		                 "${_tr_origin}" "${_tr_mode}"); then
 			_tr_ret=$((_tr_ret + 1));
 			test -n "${_tr_target}" || break
 			echo "E:upgrade"
 			test -s "${_tr_target}" \
 			  && { echo ---; cat "${_tr_target}" || :; echo ---; }
 			continue
 		fi
 
 		# post-validate
 		if ! test_runner_validate "${_tr_schema_t}" "${_tr_target}"; then
 			_tr_ret=$((_tr_ret + 1)); echo "E:post-validate"; continue
 		fi
 
 		echo "OK"
 	done
 
 	log2_or_0_return ${_tr_ret}
 }
 
 #
 # particular test variations
 # stdin: granular test specification(s) if any
 #
 
 test2to3() {
 	_t23_pattern=
 
 	while read _t23_spec; do
 		_t23_spec=${_t23_spec%.xml}
 		_t23_spec=${_t23_spec%\*}
 		_t23_pattern="${_t23_pattern} -name ${_t23_spec}*.xml -o"
 	done
 	test -z "${_t23_pattern}" || _t23_pattern="( ${_t23_pattern%-o} )"
 
 	find test-2 -name test-2 -o -type d -prune \
 	  -o -name '*.xml' ${_t23_pattern} -print | env LC_ALL=C sort \
 	  | { case " $* " in
 	      *\ -C\ *) test_cleaner;;
 	      *\ -S\ *) test_selfcheck -o=2.10;;
 	      *\ -X\ *) test_explanation -o=2.10;;
 	      *\ -W\ *) test_browser;;
 	      *) test_runner -o=2.10 -t=3.0 "$@" || return $?;;
 	      esac; }
 }
 tests="${tests} test2to3"
 
 # -B
 # -D
 # -G ... see usage
 cts_scheduler() {
 	_tcp_mode=0
 	_tcp_ret=0
 	_tcp_validatewith=
 	_tcp_schema_o=
 	_tcp_schema_t=
 	_tcp_template=
 
 	find ../cts/scheduler -name scheduler -o -type d -prune \
 	  -o -name '*.xml' -print | env LC_ALL=C sort \
 	  | { case " $* " in
 	      *\ -C\ *) test_cleaner -r;;
 	      *\ -S\ *) emit_result "not implemented" "option -S";;
 	      *\ -X\ *) emit_result "not implemented" "option -X";;
 	      *)
 		while test $# -gt 0; do
 			case "$1" in
 			-G) _tcp_mode=$((_tcp_mode | (1 << 0)));;
 			-D) _tcp_mode=$((_tcp_mode | (1 << 1)));;
 			-B) _tcp_mode=$((_tcp_mode | (1 << 2)));;
 			esac
 			shift
 		done
 		while read _tcp_origin; do
 			_tcp_validatewith=$(${XSLTPROCESSOR} - "${_tcp_origin}" <<-EOF
 	<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 	<xsl:output method="text" encoding="UTF-8"/>
 	<xsl:template match="/">
 	  <xsl:choose>
 	    <xsl:when test="starts-with(cib/@validate-with, 'pacemaker-')">
 	      <xsl:variable name="Version" select="substring-after(cib/@validate-with, 'pacemaker-')"/>
 	      <xsl:choose>
 	        <xsl:when test="contains(\$Version, '.')">
 	          <xsl:value-of select="substring-before(\$Version, '.')"/>
 	        </xsl:when>
 	        <xsl:otherwise>
 	          <xsl:value-of select="cib/@validate-with"/>
 	        </xsl:otherwise>
 	      </xsl:choose>
 	    </xsl:when>
 	    <xsl:otherwise>
 	     <xsl:value-of select="cib/@validate-with"/>
 	    </xsl:otherwise>
 	  </xsl:choose>
 	</xsl:template>
 	</xsl:stylesheet>
 EOF
 )
 			_tcp_schema_t=${_tcp_validatewith}
 			case "${_tcp_validatewith}" in
 			1) _tcp_schema_o=1.3;;
 			2) _tcp_schema_o=2.10;;
 			# only for gradual refinement as upgrade-2.10.xsl under
 			# active development, move to 3.x when schema v4 emerges
 			3) _tcp_schema_o=2.10
 			   _tcp_schema_t=2;;
 			*) emit_error \
 			   "need to skip ${_tcp_origin} (schema: ${_tcp_validatewith})"
 			   continue;;
 			esac
 			_tcp_template="upgrade-${_tcp_schema_o}.xsl"
 			_tcp_schema_t="pacemaker-$((_tcp_schema_t + 1)).0.rng"
 			test "${_tcp_schema_o%%.*}" = "${_tcp_validatewith}" \
 			  && _tcp_schema_o="pacemaker-${_tcp_schema_o}.rng" \
 			  || _tcp_schema_o="${_tcp_schema_t}"
 
 			# pre-validate
 			if test "${_tcp_schema_o}" != "${_tcp_schema_t}" \
 			  && ! test_runner_validate "${_tcp_schema_o}" "${_tcp_origin}"; then
 				_tcp_ret=$((_tcp_ret + 1)); echo "E:pre-validate"; continue
 			fi
 
 			# upgrade
 			test "$((_tcp_mode & (1 << 0)))" -ne 0 \
 			  || ln -fs "$(pwd)/${_tcp_origin}" "${_tcp_origin%.*}.ref"
 			if ! _tcp_target=$(test_runner_upgrade "${_tcp_template}" \
 			                   "${_tcp_origin}" "${_tcp_mode}"); then
 				_tcp_ret=$((_tcp_ret + 1));
 				test -n "${_tcp_target}" || break
 				echo "E:upgrade"
 				test -s "${_tcp_target}" \
 				  && { echo ---; cat "${_tcp_target}" || :; echo ---; }
 				continue
 			fi
 			test "$((_tcp_mode & (1 << 0)))" -ne 0 \
 			  || rm -f "${_tcp_origin%.*}.ref"
 
 			# post-validate
 			if ! test_runner_validate "${_tcp_schema_t}" "${_tcp_target}"; then
 				_tcp_ret=$((_tcp_ret + 1)); echo "E:post-validate"; continue
 			fi
 
 			test "$((_tcp_mode & (1 << 0)))" -eq 0 \
 			  || mv "${_tcp_target}" "${_tcp_origin}"
 		done; log2_or_0_return ${_tcp_ret};;
 	      esac; }
 }
 tests="${tests} cts_scheduler"
 
 #
 # "framework"
 #
 
 # option-likes ... options to be passed down
 # argument-likes ... drives a test selection
 test_suite() {
 	_ts_pass=
 	_ts_select=
 	_ts_select_full=
 	_ts_test_specs=
 	_ts_global_ret=0
 	_ts_ret=0
 
 	while test $# -gt 0; do
 		case "$1" in
 		-) printf '%s\n' 'waiting for tests specified at stdin...';
 		   while read _ts_spec; do _ts_select="${_ts_spec}@$1"; done;;
 		-*) _ts_pass="${_ts_pass} $1";;
 		*) _ts_select_full="${_ts_select_full}@$1"
 		   _ts_select="${_ts_select}@${1%%/*}";;
 		esac
 		shift
 	done
 	_ts_select="${_ts_select}@"
 	_ts_select_full="${_ts_select_full}@"
 
 	for _ts_test in ${tests}; do
 
 		while true; do
 			case "${_ts_select}" in
 			*@${_ts_test}@*)
 			_ts_select="${_ts_select%@${_ts_test}@*}"\
 "@${_ts_select#*@${_ts_test}@}"
 			break
 			;;
 			@) case "${_ts_test}" in test*) break;; esac
 			;;
 			esac
 			continue 2  # move on to matching with next local test
 		done
 
 		_ts_test_specs=
 		while true; do
 			case "${_ts_select_full}" in
 			*@${_ts_test}/*)
 				_ts_test_full="${_ts_test}/${_ts_select_full#*@${_ts_test}/}"
 				_ts_test_full="${_ts_test_full%%@*}"
 				_ts_select_full="${_ts_select_full%@${_ts_test_full}@*}"\
 "@${_ts_select_full#*@${_ts_test_full}@}"
 				_ts_test_specs="${_ts_test_specs} ${_ts_test_full#*/}"
 			;;
 			*)
 			break
 			;;
 			esac
 		done
 
 		for _ts_test_spec in ${_ts_test_specs}; do
 			printf '%s\n' "${_ts_test_spec}"
 		done | "${_ts_test}" ${_ts_pass} || _ts_ret=$?
 
 		test ${_ts_ret} = 0 \
 		  && emit_result ${_ts_ret} "${_ts_test}" \
 		  || emit_result "at least 2^$((_ts_ret - 1))" "${_ts_test}"
 		log2_or_0_add ${_ts_global_ret} ${_ts_ret}
 		_ts_global_ret=$?
 	done
 	if test "${_ts_select}" != @; then
 		emit_error "Non-existing test(s):$(echo "${_ts_select}" \
 		                                   | tr '@' ' ')"
 		log2_or_0_add ${_ts_global_ret} 1 || _ts_global_ret=$?
 	fi
 
 	return ${_ts_global_ret}
 }
 
 # NOTE: big letters are dedicated for per-test-set behaviour,
 #       small ones for generic/global behaviour
 usage() {
 	printf \
-	  '%s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n' \
+	  '%s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n' \
 	  "usage: $0 [-{B,C,D,G,S,X}]* [-|{${tests## }}*]" \
 	  "- when no suites (arguments) provided, \"test*\" ones get used" \
 	  "- with '-' suite specification the actual ones grabbed on stdin" \
 	  "- use '-B' to run validate-only check suppressing blanks first" \
 	  "- use '-C' to only cleanup ephemeral byproducts" \
 	  "- use '-D' to review originals vs. \"referential\" outcomes" \
 	  "- use '-G' to generate \"referential\" outcomes" \
 	  "- use '-S' for template self-check (requires net access)" \
+	  "- use '-W' to run browser-based, on-the-fly diff'ing test drive" \
 	  "- use '-X' to show explanatory details about the upgrade" \
 	  "- test specification can be granular, e.g. 'test2to3/022'"
 	printf \
-	  '\n%s\n  %s\n  %s\n  %s\n  %s\n  %s\n' \
+	  '\n%s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n  %s\n' \
 	  'environment variables affecting the run + default/current values:' \
 	  "- DIFF (${DIFF}): tool to compute and show differences of 2 files" \
 	  "- DIFFOPTS (${DIFFOPTS}): options to the above tool" \
 	  "- DIFFPAGER (${DIFFPAGER}): possibly accompanying the above tool" \
 	  "- RNGVALIDATOR (${RNGVALIDATOR}): RelaxNG validator" \
-	  "- XSLTPROCESSOR (${_XSLTPROCESSOR}): XSLT 1.0 capable processor"
+	  "- XSLTPROCESSOR (${_XSLTPROCESSOR}): XSLT 1.0 capable processor" \
+	  "- HTTPPORT (${HTTPPORT}): port used by test drive HTTP server run" \
+	  "- WEBBROWSER (${WEBBROWSER}): used for in-browser test drive"
 }
 
 main() {
 	_main_pass=
 	_main_bailout=0
 	_main_ret=0
 
 	while test $# -gt 0; do
 		case "$1" in
 		-h) usage; exit;;
 		-C|-G|-S|-X) _main_bailout=1;;
 		esac
 		_main_pass="${_main_pass} $1"
 		shift
 	done
 
 	test_suite ${_main_pass} || _main_ret=$?
 	test ${_main_bailout} -eq 1 && return ${_main_ret} \
 	  || test_suite -C ${_main_pass} >/dev/null || true
 	test ${_main_ret} = 0 && emit_result ${_main_ret} "Overall suite" \
 	  || emit_result "at least 2^$((_main_ret - 1))" "Overall suite"
 
 	return ${_main_ret}
 }
 
 main "$@"
diff --git a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml
index 699d3d0bd8..70bedfdad3 100644
--- a/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml
+++ b/xml/test-2/010-rsc_colocation-dropped-for-noop-sa.xml
@@ -1,61 +1,62 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <!--
  Contrieved example of how rsc_colocation/@score-attribute might have been used
 
  This was never implemented and, apparently, will not work.
  -->
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063">
         <instance_attributes id="virt-063-attrs">
           <nvpair id="virt-063-AddrHttpdTogether" name="AddrHttpdTogether" value="INFINITY"/>
         </instance_attributes>
       </node>
       <node id="virt-064" uname="virt-064">
         <instance_attributes id="virt-064-attrs">
           <nvpair id="virt-064-AddrHttpdTogether" name="AddrHttpdTogether" value="INFINITY"/>
         </instance_attributes>
       </node>
       <node id="virt-069" uname="virt-069">
         <instance_attributes id="virt-069-attrs">
           <!-- IPaddr2 won't work here, is DNS-load-balanced or something... -->
           <nvpair id="virt-069-AddrHttpdTogether" name="AddrHttpdTogether" value="-INFINITY"/>
         </instance_attributes>
       </node>
 
     </nodes>
     <resources>
 
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints>
 
       <rsc_order id="order-addr-httpd" first="myAddr" then="myHttpd"/>
 
       <!-- this never worked like that -->
       <rsc_colocation id="colocation-addr-httpd" rsc="myHttpd" with-rsc="myAddr"
                       score-attribute="AddrHttpdTogether"/>
 
     </constraints>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/020-rsc-requires-inline.xml b/xml/test-2/020-rsc-requires-inline.xml
index 66b1d0604c..630bb18bd7 100644
--- a/xml/test-2/020-rsc-requires-inline.xml
+++ b/xml/test-2/020-rsc-requires-inline.xml
@@ -1,44 +1,45 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <!-- relying on order (+ colocation) to guarantee "requires"
                transitively (unfencing/fencing/quorum)? -->
           <op id="myAddr-start" name="start" interval="0" timeout="40s"
               requires="nothing"/>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints>
 
       <rsc_order id="order-addr-httpd" first="myAddr" then="myHttpd"/>
       <rsc_colocation id="colocation-addr-httpd" rsc="myHttpd" with-rsc="myAddr" score="INFINITY"/>
 
     </constraints>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/021-rsc-requires-nvpair.xml b/xml/test-2/021-rsc-requires-nvpair.xml
index e2214efe40..6f75c200e5 100644
--- a/xml/test-2/021-rsc-requires-nvpair.xml
+++ b/xml/test-2/021-rsc-requires-nvpair.xml
@@ -1,47 +1,48 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-start" name="start" interval="0" timeout="40s">
             <meta_attributes id="myAddr-start-metaparams">
               <!-- relying on order (+ colocation) to guarantee "requires"
                    transitively (unfencing/fencing/quorum)? -->
               <nvpair id="myAddr-start-requires" name="requires" value="nothing"/>
             </meta_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints>
 
       <rsc_order id="order-addr-httpd" first="myAddr" then="myHttpd"/>
       <rsc_colocation id="colocation-addr-httpd" rsc="myHttpd" with-rsc="myAddr" score="INFINITY"/>
 
     </constraints>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/022-rsc-requires-counterexamples.xml b/xml/test-2/022-rsc-requires-counterexamples.xml
index c74e76cdd4..ce9717b31d 100644
--- a/xml/test-2/022-rsc-requires-counterexamples.xml
+++ b/xml/test-2/022-rsc-requires-counterexamples.xml
@@ -1,49 +1,50 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-start" name="start" interval="0" timeout="40s">
             <meta_attributes id="myAddr-start-metaparams">
               <!-- fake-requires != requires -->
               <nvpair id="myAddr-start-requires" name="fake-requires" value="nothing"/>
             </meta_attributes>
           </op>
           <!-- stop != start -->
           <op id="myAddr-stop" name="stop" interval="0" timeout="40s"
               requires="nothing"/>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints>
 
       <rsc_order id="order-addr-httpd" first="myAddr" then="myHttpd"/>
       <rsc_colocation id="colocation-addr-httpd" rsc="myHttpd" with-rsc="myAddr" score="INFINITY"/>
 
     </constraints>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/023-rsc-requires-no-override.xml b/xml/test-2/023-rsc-requires-no-override.xml
index 5de3efebf1..8f3d765ef1 100644
--- a/xml/test-2/023-rsc-requires-no-override.xml
+++ b/xml/test-2/023-rsc-requires-no-override.xml
@@ -1,65 +1,66 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <!-- possible override from op attribute -->
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-start" name="start" interval="0" timeout="40s"
               requires="nothing"/>
           <!-- stop != start -->
           <op id="myAddr-stop" name="stop" interval="0" timeout="40s"/>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
         <meta_attributes id="myAddr-meta">
           <nvpair id="myAddr-requires" name="requires" value="quorum"/>
         </meta_attributes>
       </primitive>
 
       <!-- possible override from op's meta-attribute -->
       <clone id="master">
         <meta_attributes id="master-meta">
           <nvpair id="master-promotable" name="promotable" value="true"/>
           <nvpair id="master-promoted-node-max" name="promoted-node-max" value="1"/>
           <nvpair id="master-clone-max" name="clone-max" value="3"/>
           <nvpair id="master-promoted-max" name="promoted-max" value="1"/>
           <nvpair id="master-clone-node-max" name="clone-node-max" value="1"/>
         </meta_attributes>
         <primitive id="stateful" class="ocf" type="Stateful" provider="pacemaker">
           <operations>
             <op id="stateful-monitor-15s" interval="15s" name="monitor" timeout="60s"/>
             <op id="stateful-monitor-16s" interval="16s" name="monitor" timeout="60s" role="Master"/>
             <op id="stateful-promote" interval="0" name="promote" timeout="40s">
               <meta_attributes id="stateful-promote-meta">
                 <nvpair id="stateful-promote-requires" name="requires" value="nothing"/>
               </meta_attributes>
             </op>
             <!-- demote != promote -->
             <op id="stateful-demote" interval="0" name="demote" timeout="40s">
               <meta_attributes id="stateful-demote-meta">
                 <nvpair id="stateful-demote-requires" name="requires" value="nothing"/>
               </meta_attributes>
             </op>
           </operations>
           <meta_attributes id="stateful-meta">
             <nvpair id="stateful-requires" name="requires" value="quorum"/>
           </meta_attributes>
         </primitive>
       </clone>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/024-rsc-requires-no-selfclash.xml b/xml/test-2/024-rsc-requires-no-selfclash.xml
index f44737e2d4..096c61c2a6 100644
--- a/xml/test-2/024-rsc-requires-no-selfclash.xml
+++ b/xml/test-2/024-rsc-requires-no-selfclash.xml
@@ -1,140 +1,141 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <!-- potential clash between pre-existing
            meta_attributes/nvpair[@name = 'requires'] vs.
            op[@name = 'start'
               or
               @name = 'promote']/@requires
            and/or
            op[@name = 'start'
            or
            @name = 'promote']/meta_attributes/nvpair[@name = 'requires'] -->
       <primitive id="myAddr1" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr1-monitor" name="monitor" interval="30s"/>
           <op id="myAddr1-start" name="start" interval="0" timeout="40s"
               requires="nothing">
             <meta_attributes id="myAddr1-start-meta">
               <nvpair id="myAddr1-start-requires" name="requires" value="stonith"/>
             </meta_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr1-params">
           <nvpair id="myAddr1-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
         <meta_attributes id="myAddr1-meta">
           <nvpair id="myAddr1-requires" name="requires" value="quorum"/>
         </meta_attributes>
       </primitive>
 
       <!-- potential clash between op[@name = 'start'
                                       or
                                       @name = 'promote']/@requires
            and op[@name = 'start'
                   or
                   @name = 'promote']/meta_attributes/nvpair[@name = 'requires']
            (would-eliminate-override-meta-attribute is missing,
            allowing for direct clash in the propagation logic) -->
       <primitive id="myAddr2" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr2-monitor" name="monitor" interval="30s"/>
           <op id="myAddr2-start" name="start" interval="0" timeout="40s"
               requires="nothing">
             <meta_attributes id="myAddr2-start-meta">
               <nvpair id="myAddr2-start-requires" name="requires" value="stonith"/>
             </meta_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr2-params">
           <nvpair id="myAddr2-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <!-- potential clash between multiple op[@name = 'start'
                                                or
                                                @name = 'promote']/@requires
            (would-eliminate-override-meta-attribute is missing,
            allowing for direct clash in the propagation logic) -->
       <clone id="master1">
         <meta_attributes id="master1-meta">
           <nvpair id="master1-promotable" name="promotable" value="true"/>
           <nvpair id="master1-promoted-node-max" name="promoted-node-max" value="1"/>
           <nvpair id="master1-clone-max" name="clone-max" value="3"/>
           <nvpair id="master1-promoted-max" name="promoted-max" value="1"/>
           <nvpair id="master1-clone-node-max" name="clone-node-max" value="1"/>
         </meta_attributes>
         <primitive id="stateful1" class="ocf" type="Stateful" provider="pacemaker">
           <operations>
             <op id="stateful1-monitor-15s" interval="15s" name="monitor" timeout="60s"/>
             <op id="stateful1-monitor-16s" interval="16s" name="monitor" timeout="60s" role="Master"/>
             <op id="stateful1-promote" interval="0" name="promote" timeout="40s"
                 requires="quorum"/>
             <op id="stateful1-start" interval="0" name="start" timeout="40s"
                 requires="fencing"/>
             <!-- demote != promote -->
             <op id="stateful1-demote" interval="0" name="demote" timeout="40s">
               <meta_attributes id="stateful1-demote-meta">
                 <nvpair id="stateful1-demote-requires" name="requires" value="nothing"/>
               </meta_attributes>
             </op>
           </operations>
         </primitive>
       </clone>
 
       <!-- potential clash between multiple
            op[@name = 'start'
               or
               @name = 'promote']/meta_attributes/nvpair[@name = 'requires']
            (would-eliminate-override-meta-attribute is missing,
            allowing for direct clash in the propagation logic) -->
       <clone id="master2">
         <meta_attributes id="master2-meta">
           <nvpair id="master2-promotable" name="promotable" value="true"/>
           <nvpair id="master2-promoted-node-max" name="promoted-node-max" value="1"/>
           <nvpair id="master2-clone-max" name="clone-max" value="3"/>
           <nvpair id="master2-promoted-max" name="promoted-max" value="1"/>
           <nvpair id="master2-clone-node-max" name="clone-node-max" value="1"/>
         </meta_attributes>
         <primitive id="stateful2" class="ocf" type="Stateful" provider="pacemaker">
           <operations>
             <op id="stateful2-monitor-15s" interval="15s" name="monitor" timeout="60s"/>
             <op id="stateful2-monitor-16s" interval="16s" name="monitor" timeout="60s" role="Master"/>
 	    <op id="stateful2-promote" interval="0" name="promote" timeout="40s">
               <meta_attributes id="stateful2-promote-meta1">
                 <nvpair id="stateful2-promote-requires1-1" name="requires" value="quorum"/>
                 <nvpair id="stateful2-promote-requires1-2" name="requires" value="nothing"/>
               </meta_attributes>
               <meta_attributes id="stateful2-promote-meta2">
                 <nvpair id="stateful2-promote-requires2-1" name="requires" value="unfencing"/>
               </meta_attributes>
 	    </op>
             <op id="stateful2-start" interval="0" name="start" timeout="40s">
               <meta_attributes id="stateful2-promote-meta3">
                 <nvpair id="stateful2-promote-requires3-1" name="requires" value="fencing"/>
               </meta_attributes>
 	    </op>
             <!-- demote != promote -->
             <op id="stateful2-demote" interval="0" name="demote" timeout="40s">
               <meta_attributes id="stateful2-promote-meta">
                 <nvpair id="stateful2-promote-requires" name="requires" value="nothing"/>
               </meta_attributes>
             </op>
           </operations>
         </primitive>
       </clone>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/030-clu-props-plain-rename.xml b/xml/test-2/030-clu-props-plain-rename.xml
index 8186117d20..f7a0a52d8a 100644
--- a/xml/test-2/030-clu-props-plain-rename.xml
+++ b/xml/test-2/030-clu-props-plain-rename.xml
@@ -1,25 +1,26 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config>
       <cluster_property_set id="cluster-opts">
         <nvpair id="cluster-opts-cluster_recheck_interval" name="cluster_recheck_interval" value="10min"/>
         <nvpair id="cluster-opts-dc_deadtime" name="dc_deadtime" value="15s"/>
         <nvpair id="cluster-opts-election_timeout" name="election_timeout" value="90s"/>
         <nvpair id="cluster-opts-no_quorum_policy" name="no_quorum_policy" value="freeze"/>
         <nvpair id="cluster-opts-remove_after_stop" name="remove_after_stop" value="false"/>
         <nvpair id="cluster-opts-shutdown_escalation" name="shutdown_escalation" value="15min"/>
         <nvpair id="cluster-opts-startup_fencing" name="startup_fencing" value="true"/>
         <nvpair id="cluster-opts-stonith_action" name="stonith_action" value="off"/>
         <nvpair id="cluster-opts-stonith_enabled" name="stonith_enabled" value="off"/>
         <nvpair id="cluster-opts-stop_orphan_actions" name="stop_orphan_actions" value="true"/>
         <nvpair id="cluster-opts-stop_orphan_resources" name="stop_orphan_resources" value="true"/>
         <nvpair id="cluster-opts-symmetric_cluster" name="symmetric_cluster" value="true"/>
         <nvpair id="cluster-opts-transition_idle_timeout" name="transition_idle_timeout" value="50s"/>
       </cluster_property_set>
     </crm_config>
     <nodes/>
     <resources/>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/031-clu-props-drop.xml b/xml/test-2/031-clu-props-drop.xml
index 9d33788a1c..663569c398 100644
--- a/xml/test-2/031-clu-props-drop.xml
+++ b/xml/test-2/031-clu-props-drop.xml
@@ -1,20 +1,21 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config>
       <cluster_property_set id="cluster-opts">
         <nvpair id="cluster-opts-cluster-infrastructure" name="cluster-infrastructure" value="heartbeat"/>
         <nvpair id="cluster-opts-default-migration-threshold" name="default-migration-threshold" value="10"/>
         <nvpair id="cluster-opts-default_migration_threshold" name="default_migration_threshold" value="10"/>
         <nvpair id="cluster-opts-expected-quorum-votes" name="expected-quorum-votes" value="3"/>
         <nvpair id="cluster-opts-notification-agent" name="notification-agent" value="/etc/pacemaker/notif.sh"/>
       </cluster_property_set>
       <cluster_property_set id="cluster-opts-2">
         <nvpair id="cluster-opts-cluster-infrastructure-2" name="cluster-infrastructure" value="corosync"/>
       </cluster_property_set>
     </crm_config>
     <nodes/>
     <resources/>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/032-clu-props-move.xml b/xml/test-2/032-clu-props-move.xml
index aff84ebafb..1f34d7b814 100644
--- a/xml/test-2/032-clu-props-move.xml
+++ b/xml/test-2/032-clu-props-move.xml
@@ -1,15 +1,16 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config>
       <cluster_property_set id="cluster-opts">
         <nvpair id="cluster-opts-default-action-timeout" name="default-action-timeout" value="30s"/>
         <nvpair id="cluster-opts-default-resource-stickiness" name="default-resource-stickiness" value="100"/>
         <nvpair id="cluster-opts-is-managed-default" name="is-managed-default" value="true"/>
       </cluster_property_set>
     </crm_config>
     <nodes/>
     <resources/>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/033-clu-props-move-merge.xml b/xml/test-2/033-clu-props-move-merge.xml
index a5d681906e..c34085b15e 100644
--- a/xml/test-2/033-clu-props-move-merge.xml
+++ b/xml/test-2/033-clu-props-move-merge.xml
@@ -1,20 +1,21 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config>
       <cluster_property_set id="cluster-opts">
         <nvpair id="cluster-opts-default-action-timeout" name="default-action-timeout" value="30s"/>
         <nvpair id="cluster-opts-default-resource-stickiness" name="default-resource-stickiness" value="100"/>
         <nvpair id="cluster-opts-is-managed-default" name="is-managed-default" value="true"/>
       </cluster_property_set>
     </crm_config>
     <rsc_defaults>
       <meta_attributes id="rsc-defaults">
         <nvpair id="rsc-defaults-is-managed" name="is-managed" value="false"/>
       </meta_attributes>
     </rsc_defaults>
     <nodes/>
     <resources/>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/034-clu-props-move-redef.xml b/xml/test-2/034-clu-props-move-redef.xml
index 7f65755a78..fcadf20a7a 100644
--- a/xml/test-2/034-clu-props-move-redef.xml
+++ b/xml/test-2/034-clu-props-move-redef.xml
@@ -1,14 +1,15 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config>
       <cluster_property_set id="cluster-opts">
         <nvpair id="cluster-opts-default-resource-failure-stickiness" name="default-resource-failure-stickiness" value="-INFINITY"/>
         <nvpair id="cluster-opts-default_resource_failure_stickiness" name="default_resource_failure_stickiness" value="0"/>
       </cluster_property_set>
     </crm_config>
     <nodes/>
     <resources/>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/040-nodes-rename-type.xml b/xml/test-2/040-nodes-rename-type.xml
index fe19d91b84..939b768c8d 100644
--- a/xml/test-2/040-nodes-rename-type.xml
+++ b/xml/test-2/040-nodes-rename-type.xml
@@ -1,15 +1,16 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063" type="normal"/>
       <node id="virt-064" uname="virt-064" type="normal"/>
       <node id="virt-069" uname="virt-069" type="member"/>
 
     </nodes>
     <resources/>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/050-rsc-attrs-instance-plain-rename.xml b/xml/test-2/050-rsc-attrs-instance-plain-rename.xml
index 02db4cd556..ccf2404130 100644
--- a/xml/test-2/050-rsc-attrs-instance-plain-rename.xml
+++ b/xml/test-2/050-rsc-attrs-instance-plain-rename.xml
@@ -1,24 +1,25 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes/>
     <resources>
 
       <primitive class="stonith" id="fence-vbox" type="fence_vbox">
         <instance_attributes id="fence-vbox-params">
           <nvpair id="fence-vbox-params-ipaddr" name="ipaddr" value="192.0.3.10"/>
           <nvpair id="fence-vbox-params-login" name="login" value="vboxadmin"/>
           <nvpair id="fence-vbox-params-passwd_script" name="passwd_script" value="/usr/local/cluster/vboxpass.sh"/>
           <nvpair id="fence-vbox-params-plug" name="plug" value="vboxhost"/>
           <nvpair id="fence-vbox-pcmk_monitor_cmd" name="pcmk_monitor_cmd" value="metadata"/>
         </instance_attributes>
         <operations>
           <op id="fence-vbox-monitor" interval="60s" name="monitor"/>
         </operations>
       </primitive>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.xml b/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.xml
index 01a2782db9..75ad2a7485 100644
--- a/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.xml
+++ b/xml/test-2/051-rsc-attrs-instance-pcmk_arg_map.xml
@@ -1,50 +1,51 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes/>
     <resources>
 
       <primitive class="stonith" id="fence-vbox1" type="fence_vbox">
         <instance_attributes id="fence-vbox1-params">
           <nvpair id="fence-vbox1-params-ipaddr" name="ipaddr" value="192.0.3.10"/>
           <nvpair id="fence-vbox1-params-login" name="login" value="vboxadmin"/>
           <nvpair id="fence-vbox1-params-passwd_script" name="passwd_script" value="/usr/local/cluster/vboxpass.sh"/>
           <nvpair id="fence-vbox1-params-plug" name="plug" value="vboxhost"/>
           <nvpair id="fence-vbox1-pcmk_arg_map" name="pcmk_arg_map" value="port:port"/>
         </instance_attributes>
         <operations>
           <op id="fence-vbox1-monitor" interval="60s" name="monitor"/>
         </operations>
       </primitive>
 
       <primitive class="stonith" id="fence-vbox2" type="fence_vbox">
         <instance_attributes id="fence-vbox2-params">
           <nvpair id="fence-vbox2-params-ipaddr" name="ipaddr" value="192.0.3.10"/>
           <nvpair id="fence-vbox2-params-login" name="login" value="vboxadmin"/>
           <nvpair id="fence-vbox2-params-passwd_script" name="passwd_script" value="/usr/local/cluster/vboxpass.sh"/>
           <nvpair id="fence-vbox2-params-plug" name="plug" value="vboxhost"/>
           <nvpair id="fence-vbox2-pcmk_arg_map" name="pcmk_arg_map" value="dropme:sure,port:port"/>
         </instance_attributes>
         <operations>
           <op id="fence-vbox2-monitor" interval="60s" name="monitor"/>
         </operations>
       </primitive>
 
       <primitive class="stonith" id="fence-vbox3" type="fence_vbox">
         <instance_attributes id="fence-vbox3-params">
           <nvpair id="fence-vbox3-params-ipaddr" name="ipaddr" value="192.0.3.10"/>
           <nvpair id="fence-vbox3-params-login" name="login" value="vboxadmin"/>
           <nvpair id="fence-vbox3-params-passwd_script" name="passwd_script" value="/usr/local/cluster/vboxpass.sh"/>
           <nvpair id="fence-vbox3-params-plug" name="plug" value="vboxhost"/>
           <nvpair id="fence-vbox3-pcmk_arg_map" name="pcmk_arg_map" value="port:port,dropme:justhope"/>
         </instance_attributes>
         <operations>
           <op id="fence-vbox3-monitor" interval="60s" name="monitor"/>
         </operations>
       </primitive>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/060-rsc-attrs-meta-isolation.xml b/xml/test-2/060-rsc-attrs-meta-isolation.xml
index 3f49b2a442..9c7dcb9e88 100644
--- a/xml/test-2/060-rsc-attrs-meta-isolation.xml
+++ b/xml/test-2/060-rsc-attrs-meta-isolation.xml
@@ -1,26 +1,27 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes/>
     <resources>
 
       <!-- from c713bbe39:pengine/test10/isolation-restart-all.xml -->
       <primitive class="ocf" id="fake" provider="heartbeat" type="Dummy">
         <instance_attributes id="fake-instance_attributes">
           <nvpair id="fake-instance_attributes-docker_image" name="pcmk_docker_image" value="centos:dock-wrapper-test"/>
           <nvpair id="fake-instance_attributes-docker_privileged" name="pcmk_docker_privileged" value="false"/>
         </instance_attributes>
         <operations>
           <op id="fake-monitor-interval-60s" interval="60s" name="monitor"/>
         </operations>
         <meta_attributes id="fake-meta_attributes">
           <nvpair id="fake-meta_attributes-isolation-wrapper" name="isolation-wrapper" value="docker-wrapper"/>
           <nvpair id="fake-meta_attributes-isolation-wrapper2" name="isolation-wrapper" value="docker-wrapper"/>
         </meta_attributes>
       </primitive>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/061-rsc-attrs-meta-exchange.xml b/xml/test-2/061-rsc-attrs-meta-exchange.xml
index 99ff8559b0..cb0c0ebcb9 100644
--- a/xml/test-2/061-rsc-attrs-meta-exchange.xml
+++ b/xml/test-2/061-rsc-attrs-meta-exchange.xml
@@ -1,29 +1,30 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes/>
     <resources>
 
       <primitive class="ocf" id="res1" provider="heartbeat" type="Dummy">
         <operations>
           <op id="res1-monitor-interval-60s" interval="60s" name="monitor"/>
         </operations>
         <meta_attributes id="res1-meta_attributes">
           <nvpair id="res1-resource-failure-stickiness" name="resource-failure-stickiness" value="-INFINITY"/>
         </meta_attributes>
       </primitive>
 
       <primitive class="ocf" id="res2" provider="heartbeat" type="Dummy">
         <operations>
           <op id="res2-monitor-interval-60s" interval="60s" name="monitor"/>
         </operations>
         <meta_attributes id="res2-meta_attributes">
           <nvpair id="res2-resource-failure-stickiness" name="resource-failure-stickiness" value="0"/>
         </meta_attributes>
       </primitive>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/070-rsc-op-attrs-inst-requires-start.xml b/xml/test-2/070-rsc-op-attrs-inst-requires-start.xml
index 90a4735a5f..2661f7d0a6 100644
--- a/xml/test-2/070-rsc-op-attrs-inst-requires-start.xml
+++ b/xml/test-2/070-rsc-op-attrs-inst-requires-start.xml
@@ -1,48 +1,49 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <!-- borrowed from 021-rsc-requires-nvpair -->
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-start" name="start" interval="0" timeout="40s">
             <instance_attributes id="myAddr-start-instanceparams">
               <!-- relying on order (+ colocation) to guarantee "requires"
                    transitively (unfencing/fencing/quorum)? -->
               <nvpair id="myAddr-start-requires" name="requires" value="nothing"/>
             </instance_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints>
 
       <rsc_order id="order-addr-httpd" first="myAddr" then="myHttpd"/>
       <rsc_colocation id="colocation-addr-httpd" rsc="myHttpd" with-rsc="myAddr" score="INFINITY"/>
 
     </constraints>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.xml b/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.xml
index b6f87bfc2f..4f364f469d 100644
--- a/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.xml
+++ b/xml/test-2/071-rsc-op-attrs-inst-requires-nonstart.xml
@@ -1,48 +1,49 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <!-- borrowed from 021-rsc-requires-nvpair -->
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-stop" name="stop" interval="0" timeout="40s">
             <instance_attributes id="myAddr-stop-instanceparams">
               <!-- relying on order (+ colocation) to guarantee "requires"
                    transitively (unfencing/fencing/quorum)? -->
               <nvpair id="myAddr-stop-requires" name="requires" value="nothing"/>
             </instance_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s"/>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints>
 
       <rsc_order id="order-addr-httpd" first="myAddr" then="myHttpd"/>
       <rsc_colocation id="colocation-addr-httpd" rsc="myHttpd" with-rsc="myAddr" score="INFINITY"/>
 
     </constraints>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.xml b/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.xml
index c7359424bc..8af4bf12f1 100644
--- a/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.xml
+++ b/xml/test-2/072-rsc-op-attrs-inst-requires-no-override.xml
@@ -1,60 +1,61 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <!-- possible override from op's instance attribute over
            op attribute -->
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-start" name="start" interval="0" timeout="40s"
               requires="nothing">
             <instance_attributes id="myAddr-start-instance">
               <nvpair id="myAddr-start-instance-requires" name="requires" value="quorum"/>
             </instance_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <!-- possible override from op's instance attribute over
            op's meta-attribute -->
       <clone id="master">
         <meta_attributes id="master-meta">
           <nvpair id="master-promotable" name="promotable" value="true"/>
           <nvpair id="master-promoted-node-max" name="promoted-node-max" value="1"/>
           <nvpair id="master-clone-max" name="clone-max" value="3"/>
           <nvpair id="master-promoted-max" name="promoted-max" value="1"/>
           <nvpair id="master-clone-node-max" name="clone-node-max" value="1"/>
         </meta_attributes>
         <primitive id="stateful" class="ocf" type="Stateful" provider="pacemaker">
           <operations>
             <op id="stateful-monitor-15s" interval="15s" name="monitor" timeout="60s"/>
             <op id="stateful-monitor-16s" interval="16s" name="monitor" timeout="60s" role="Master"/>
             <op id="stateful-promote" interval="0" name="promote" timeout="40s">
               <meta_attributes id="stateful-promote-meta">
                 <nvpair id="stateful-promote-meta-requires" name="requires" value="nothing"/>
               </meta_attributes>
               <instance_attributes id="stateful-promote-instance">
                 <nvpair id="stateful-promote-instance-requires" name="requires" value="quorum"/>
               </instance_attributes>
             </op>
           </operations>
         </primitive>
       </clone>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.xml b/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.xml
index 736d54669f..1a1f73f712 100644
--- a/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.xml
+++ b/xml/test-2/073-rsc-op-attrs-inst-meta-meaning.xml
@@ -1,49 +1,50 @@
+<?xml-stylesheet href="../assets/upgrade-2.10-htmldiff.xsl" type="text/xsl"?>
 <cib validate-with="pacemaker-2.0" admin_epoch="0" epoch="0" num_updates="0">
   <configuration>
     <crm_config/>
     <nodes>
 
       <node id="virt-063" uname="virt-063"/>
       <node id="virt-064" uname="virt-064"/>
       <node id="virt-069" uname="virt-069"/>
 
     </nodes>
     <resources>
 
       <primitive id="myAddr" class="ocf" provider="heartbeat" type="IPaddr2">
         <operations>
           <op id="myAddr-monitor" name="monitor" interval="30s"/>
           <op id="myAddr-start" name="start" interval="0" timeout="40s">
             <instance_attributes id="myAddr-start-instance">
               <nvpair id="myAddr-start-instance-on-fail" name="on-fail" value="standby"/>
               <nvpair id="myAddr-start-instance-record-pending" name="record-pending" value="true"/>
             </instance_attributes>
           </op>
         </operations>
         <instance_attributes id="myAddr-params">
           <nvpair id="myAddr-ip" name="ip" value="192.0.2.10"/>
         </instance_attributes>
       </primitive>
 
       <primitive id="myHttpd" class="ocf" provider="heartbeat" type="apache">
         <operations>
           <op id="myHttpd-monitor" name="monitor" interval="30s">
             <instance_attributes id="myHttpd-monitor-instance">
               <nvpair id="myHttpd-monitor-instance-timeout" name="timeout" value="20"/>
               <nvpair id="myHttpd-monitor-instance-statusurl" name="statusurl" value="http://localhost/server-status"/>
             </instance_attributes>
             <instance_attributes id="myHttpd-monitor-instance2">
               <nvpair id="myHttpd-monitor-instance2-timeout" name="timeout" value="30"/>
             </instance_attributes>
           </op>
         </operations>
         <instance_attributes id="myHttpd-params">
           <nvpair id="myHttpd-configfile" name="configfile" value="/etc/httpd/conf/httpd.conf"/>
         </instance_attributes>
       </primitive>
 
     </resources>
     <constraints/>
   </configuration>
   <status/>
 </cib>
diff --git a/xml/upgrade-2.10.xsl b/xml/upgrade-2.10.xsl
index b72bd26787..321b3c22ba 100644
--- a/xml/upgrade-2.10.xsl
+++ b/xml/upgrade-2.10.xsl
@@ -1,2524 +1,2532 @@
 <!--
  Copyright 2018 Red Hat, Inc.
  Author: Jan Pokorny <jpokorny@redhat.com>
  Part of pacemaker project
  SPDX-License-Identifier: GPL-2.0-or-later
  -->
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:cibtr="http://clusterlabs.org/ns/pacemaker/cibtr-2"
                 exclude-result-prefixes="cibtr">
 <xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
 
 <xsl:param name="cibtr:cib-min-ver" select="'3.0'"/>
 
 <!--
 
  HELPER DEFINITIONS
 
  -->
 
 <cibtr:map>
 
   <!--
    Target tag:     cluster_property_set
    Object:         ./nvpair/@name
    Selector ctxt:  ./nvpair/@value
    Move ctxt:      op_defaults ~ /cib/configuration/op_defaults
                    rsc_defaults ~ /cib/configuration/rsc_defaults
    Related commit: c1c66fe13
                    +
                    7a9891f29
                    7d0d1b0eb
                    1f643d610
                    73a5d63a8
                    +
                    642a09b22
                    0c03e366d
                    a28a558f9
    -->
   <cibtr:table for="cluster-properties" msg-prefix="Cluster properties"
                where-cases="op_defaults|rsc_defaults">
     <cibtr:replace what="cluster-infrastructure"
                    with=""
                    in-case-of="heartbeat|openais|classic openais|classic openais (with plugin)|cman"
                    msg-extra="corosync (2+) infrastructure can be used instead, though the value is not of significance"/>
 
     <cibtr:replace what="cluster_recheck_interval"
                    with="cluster-recheck-interval"/>
     <cibtr:replace what="dc_deadtime"
                    with="dc-deadtime"/>
 
     <cibtr:replace what="default-action-timeout"
                    with="timeout"
                    where="op_defaults"/>
     <cibtr:replace what="default_action_timeout"
                    with="timeout"
                    where="op_defaults"/>
 
     <cibtr:replace what="default-migration-threshold"
                    with=""
                    msg-extra="migration-threshold in rsc_defaults can be configured instead"/>
     <cibtr:replace what="default_migration_threshold"
                    with=""
                    msg-extra="migration-threshold in rsc_defaults can be configured instead"/>
 
     <cibtr:replace what="default-resource-stickiness"
                    with="resource-stickiness"
                    where="rsc_defaults"/>
     <cibtr:replace what="default_resource_stickiness"
                    with="resource-stickiness"
                    where="rsc_defaults"/>
 
     <cibtr:replace what="default-resource-failure-stickiness"
                    with="migration-threshold"
                    where="rsc_defaults"
                    in-case-of="-INFINITY"
                    redefined-as="1"/>
     <cibtr:replace what="default-resource-failure-stickiness"
                    with=""
                    msg-extra="migration-threshold in rsc_defaults can be configured instead"/>
     <cibtr:replace what="default_resource_failure_stickiness"
                    with="migration-threshold"
                    where="rsc_defaults"
                    in-case-of="-INFINITY"
                    redefined-as="1"/>
     <cibtr:replace what="default_resource_failure_stickiness"
                    with=""
                    msg-extra="migration-threshold in rsc_defaults can be configured instead"/>
 
     <cibtr:replace what="election_timeout"
                    with="election-timeout"/>
     <cibtr:replace what="expected-quorum-votes"
                    with=""
                    msg-extra="corosync (2+) infrastructure tracks quorum on its own"/>
 
     <cibtr:replace what="is-managed-default"
                    with="is-managed"
                    where="rsc_defaults"/>
     <cibtr:replace what="is_managed_default"
                    with="is-managed"
                    where="rsc_defaults"/>
     <cibtr:replace what="no_quorum_policy"
                    with="no-quorum-policy"/>
 
     <cibtr:replace what="notification-agent"
                    with=""
                    msg-extra="standalone alerts can be configured instead"/>
     <cibtr:replace what="notification-recipient"
                    with=""
                    msg-extra="standalone alerts can be configured instead"/>
 
     <cibtr:replace what="remove_after_stop"
                    with="remove-after-stop"/>
     <cibtr:replace what="shutdown_escalation"
                    with="shutdown-escalation"/>
     <cibtr:replace what="startup_fencing"
                    with="startup-fencing"/>
     <cibtr:replace what="stonith_action"
                    with="stonith-action"/>
     <cibtr:replace what="stonith_enabled"
                    with="stonith-enabled"/>
     <cibtr:replace what="stop_orphan_actions"
                    with="stop-orphan-actions"/>
     <cibtr:replace what="stop_orphan_resources"
                    with="stop-orphan-resources"/>
     <cibtr:replace what="symmetric_cluster"
                    with="symmetric-cluster"/>
     <cibtr:replace what="transition_idle_timeout"
                    with="cluster-delay"/>
   </cibtr:table>
 
   <!--
    Target tag:     node
    Object:         ./@*
    Selector ctxt:  ./@*
    Move ctxt:      N/A
    Related commit: 55ab749bf
    -->
   <cibtr:table for="cluster-node" msg-prefix="Cluster node">
     <cibtr:replace what="type"
                    with="type"
                    in-case-of="normal"
                    redefined-as="member"/>
   </cibtr:table>
 
   <!--
    Target tag:     primitive
                    template
    Object:         ./instance_attributes/nvpair/@name
    Selector ctxt:  N/A
    Move ctxt:      N/A
    Related commit: 06d4559cb
                    +
                    6c8e0be20
    -->
   <cibtr:table for="resource-instance-attributes" msg-prefix="Resource instance_attributes">
     <cibtr:replace what="pcmk_arg_map"
                    with=""/>
     <!-- simplified as pcmk_arg_map can encode multiple
          comma-separated pairs (everything would be dropped then,
          except for a single dangling case: "port" coming first) -->
     <cibtr:replace what="pcmk_arg_map"
                    with="pcmk_host_argument"
                    in-case-of-droppable-prefix="port:"/>
 
     <cibtr:replace what="pcmk_list_cmd"
                    with="pcmk_list_action"/>
     <cibtr:replace what="pcmk_monitor_cmd"
                    with="pcmk_monitor_action"/>
     <cibtr:replace what="pcmk_off_cmd"
                    with="pcmk_off_action"/>
     <cibtr:replace what="pcmk_on_cmd"
                    with="pcmk_on_action"/>
     <cibtr:replace what="pcmk_reboot_cmd"
                    with="pcmk_reboot_action"/>
     <cibtr:replace what="pcmk_status_cmd"
                    with="pcmk_status_action"/>
   </cibtr:table>
 
   <!--
    Target tag:     primitive
                    template
    Object:         ./meta_attributes/nvpair/@name
    Selector ctxt:  N/A
    Move ctxt:      N/A
    Related commit: c713bbe39
                    +
                    6052ad6da
    -->
   <cibtr:table for="resource-meta-attributes" msg-prefix="Resource meta_attributes">
     <cibtr:replace what="isolation"
                    with="target-role"
                    redefined-as="Stopped"
                    msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources"/>
     <cibtr:replace what="isolation-host"
                    with="target-role"
                    redefined-as="Stopped"
                    msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources"/>
     <cibtr:replace what="isolation-instance"
                    with="target-role"
                    redefined-as="Stopped"
                    msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources"/>
     <cibtr:replace what="isolation-wrapper"
                    with="target-role"
                    redefined-as="Stopped"
                    msg-extra="i.e. resource at hand disabled; isolation wrappers obsoleted with bundle resources"/>
 
     <cibtr:replace what="resource-failure-stickiness"
                    with="migration-threshold"
                    in-case-of="-INFINITY"
                    redefined-as="1"/>
     <cibtr:replace what="resource-failure-stickiness"
                    with=""
                    msg-extra="migration-threshold can be configured instead"/>
     <cibtr:replace what="resource_failure_stickiness"
                    with="migration-threshold"
                    in-case-of="-INFINITY"
                    redefined-as="1"/>
     <cibtr:replace what="resource_failure_stickiness"
                    with=""
                    msg-extra="migration-threshold can be configured instead"/>
   </cibtr:table>
 
   <!--
    Target tag:     primitive
                    template
    Object:         ./operations/op/@*
                    ./operations/op/meta_attributes/nvpair/@name
                    ./operations/op/instance_attributes/nvpair/@name
    Selector ctxt:  ./operations/op/@name
    Move ctxt:      meta_attributes ~ ./meta_attributes/nvpair
    Related commit: 014a543d5
    -->
   <cibtr:table for="resources-operation" msg-prefix="Resources-operation"
                where-cases="meta_attributes">
     <!-- keep this in sync with resource-operation-instance-attributes table -->
     <cibtr:replace what="requires"
                    with=""
                    msg-extra="only start/promote operation taken into account"/>
     <cibtr:replace what="requires"
                    with="requires"
                    in-case-of="start|promote"
                    where="meta_attributes"/>
   </cibtr:table>
 
   <!--
    Target tag:     primitive
                    template
    Object:         ./operations/op/instance_attributes/nvpair/@name
    Selector ctxt:  ./operations/op/@name
    Move ctxt:      per-resource-meta_attributes ~ ./meta_attributes/nvpair
                    meta_attributes ~ ./operations/op/meta_attributes/nvpair
    Related commit: 023897afc
                    3100c0e8b
    -->
   <cibtr:table for="resource-operation-instance-attributes"
                msg-prefix="Resources-operation instance_attributes"
                where-cases="meta_attributes|per-resource-meta_attributes">
     <!-- this is easier to solve through resources-operation table handling,
          in the inverse mode, but for compatibility purposes, we need to have
          it tracked here, so mark it the same way as if we were moving it over
          to sibling per-op meta_attributes (while in fact we move it up to
          per-resource meta_attributes, as if it was specified in per-op
          meta_attributes already), just use a dedicated "where-case" other
          than "meta_attributes" reserved for proper local move as mentioned;
          otherwise keep it in sync with said table -->
     <cibtr:replace what="requires"
                    with=""
                    msg-extra="only start/promote operation taken into account"/>
     <cibtr:replace what="requires"
                    with="requires"
                    in-case-of="start|promote"
                    where="per-resource-meta_attributes"/>
 
     <!-- these must have been, due to the value sourcing predence arrangement,
          shadowed by immediate op's attributes, so simply preserve their
          non-meta meaning -->
     <!--
     <cibtr:replace what="name"
                    with="name"
                    where="meta_attributes"/>
     <cibtr:replace what="interval"
                    with="interval"
                    where="meta_attributes"/>
     -->
 
     <cibtr:replace what="interval-origin"
                    with="interval-origin"
                    where="meta_attributes"/>
     <cibtr:replace what="start-delay"
                    with="start-delay"
                    where="meta_attributes"/>
 
     <cibtr:replace what="enabled"
                    with="enabled"
                    where="meta_attributes"/>
     <cibtr:replace what="on-fail"
                    with="on-fail"
                    where="meta_attributes"/>
     <cibtr:replace what="record-pending"
                    with="record-pending"
                    where="meta_attributes"/>
     <cibtr:replace what="role"
                    with="role"
                    where="meta_attributes"/>
     <cibtr:replace what="timeout"
                    with="timeout"
                    where="meta_attributes"/>
   </cibtr:table>
 
   <!--
    Target tag:     rsc_colocation
    Object:         ./@*
    Selector ctxt:  N/A
    Move ctxt:      N/A
    Related commit: 96d7ffedf
    -->
   <cibtr:table for="constraints-colocation" msg-prefix="Constraints-colocation">
     <cibtr:replace what="score-attribute"
                    with=""
                    msg-extra="was actually never in effect"/>
     <cibtr:replace what="score-attribute-mangle"
                    with=""
                    msg-extra="was actually never in effect"/>
   </cibtr:table>
 
 </cibtr:map>
 
 <xsl:variable name="cibtr:MapClusterProperties"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'cluster-properties'
                         ]"/>
 
 <xsl:variable name="cibtr:MapClusterNode"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'cluster-node'
                         ]"/>
 
 <xsl:variable name="cibtr:MapResourceInstanceAttributes"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'resource-instance-attributes'
                         ]"/>
 
 <xsl:variable name="cibtr:MapResourceMetaAttributes"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'resource-meta-attributes'
                         ]"/>
 
 <xsl:variable name="cibtr:MapResourcesOperation"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'resources-operation'
                         ]"/>
 
 <xsl:variable name="cibtr:MapResourcesOperationInstanceAttributes"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'resource-operation-instance-attributes'
                         ]"/>
 
 <xsl:variable name="cibtr:MapConstraintsColocation"
               select="document('')/xsl:stylesheet
                         /cibtr:map/cibtr:table[
                           @for = 'constraints-colocation'
                         ]"/>
 
 <!--
 
  GENERIC UTILITIES
 
  -->
 
 <!--
  Plain identity template
 
  Merely implicit-context-driven, no arguments.
  -->
 <xsl:template name="cibtr:HelperIdentity">
   <xsl:copy>
     <xsl:apply-templates select="@*|node()"
                          mode="cibtr:main"/>
   </xsl:copy>
 </xsl:template>
 
 <!--
  Emit an message about the replacement, sanity checking the source definitions
 
  Merely parameter driven, no implicit context taken into account:
  - Context: optional message prefix
  - Replacement: selected subset of cibtr:map's leaves
                 (it's considered a hard error if consists of more than 1 item)
  -->
 <xsl:template name="cibtr:MapMsg">
   <xsl:param name="Context" select="''"/>
   <xsl:param name="Replacement"/>
   <xsl:choose>
     <xsl:when test="not($Replacement)"/>
     <xsl:when test="count($Replacement) != 1">
       <xsl:message terminate="yes">
         <xsl:value-of select="concat('INTERNAL ERROR:',
                                      $Replacement/../@msg-prefix,
                                      ': count($Replacement) != 1',
                                      ' does not hold (',
                                      count($Replacement), ')')"/>
       </xsl:message>
     </xsl:when>
     <xsl:otherwise>
       <xsl:variable name="MsgPrefix" select="concat(
                                                ($Replacement|$Replacement/..)
                                                  /@msg-prefix, ': '
                                              )"/>
       <xsl:message>
         <xsl:value-of select="$MsgPrefix"/>
         <xsl:if test="$Context">
           <xsl:value-of select="concat($Context, ': ')"/>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="string($Replacement/@with)">
             <xsl:choose>
               <xsl:when test="string($Replacement/@where)">
                 <xsl:if test="not(
                                 contains(
                                   concat('|', $Replacement/../@where-cases, '|'),
                                   concat('|', $Replacement/@where, '|')
                                 )
                               )">
                   <xsl:message terminate="yes">
                     <xsl:value-of select="concat('INTERNAL ERROR:',
                                                  $Replacement/../@msg-prefix,
                                                  ': $Replacement/@where (',
                                                  $Replacement/@where, ') not in ',
                                                  concat('|',
                                                  $Replacement/../@where-cases,
                                                  '|'))"/>
                   </xsl:message>
                 </xsl:if>
                 <xsl:value-of select="concat('moving ', $Replacement/@what,
                                              ' under ', $Replacement/@where)"/>
               </xsl:when>
               <xsl:when test="$Replacement/@with = $Replacement/@what">
                 <xsl:value-of select="concat('keeping ', $Replacement/@what)"/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:value-of select="concat('renaming ', $Replacement/@what)"/>
               </xsl:otherwise>
             </xsl:choose>
             <xsl:value-of select="concat(' as ', $Replacement/@with)"/>
             <xsl:if test="$Replacement/@where">
               <xsl:value-of select="' unless already defined there'"/>
             </xsl:if>
           </xsl:when>
           <xsl:otherwise>
             <xsl:value-of select="concat('dropping ', $Replacement/@what)"/>
           </xsl:otherwise>
         </xsl:choose>
         <xsl:if test="string($Replacement/@redefined-as)">
           <xsl:value-of select="concat(', redefined as ',
                                        $Replacement/@redefined-as)"/>
           <xsl:if test="$Replacement/@in-case-of">
             <xsl:value-of select="','"/>
           </xsl:if>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="string($Replacement/@in-case-of)">
             <xsl:value-of select="concat(' for matching ',
                                          $Replacement/@in-case-of)"/>
           </xsl:when>
           <xsl:when test="$Replacement/@in-case-of">
             <xsl:value-of select="' for matching &quot;empty string&quot;'"/>
           </xsl:when>
           <xsl:when test="$Replacement/@in-case-of-droppable-prefix">
             <xsl:value-of select="concat(' for matching ',
                                     $Replacement/@in-case-of-droppable-prefix,
                                     ' prefix that will, meanwhile, get dropped'
                                   )"/>
           </xsl:when>
         </xsl:choose>
       </xsl:message>
       <xsl:if test="$Replacement/@msg-extra">
         <xsl:message>
           <xsl:value-of select="concat($MsgPrefix, '... ',
                                        $Replacement/@msg-extra)"/>
         </xsl:message>
       </xsl:if>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
 
 <!--
  Produce a denormalized space if not present in the input (cf. trick A.)
 
  Merely parameter driven, no implicit context taken into account:
  - Source: input selection or result tree fragment to evaluate
  - ResultTreeFragment: optional self-explanatory flag related to Source
  -->
 <xsl:template name="cibtr:HelperDenormalizedSpace">
   <xsl:param name="Source"/>
   <xsl:param name="ResultTreeFragment" select="false()"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:choose>
     <xsl:when test="not($ResultTreeFragment)">
       <!-- intention here is that immediately surrounding text (mostly expected
            to be just indenting whitespace) and comments will be preserved;
            in case no denormalized space is present, " " is injected -->
       <xsl:variable name="ExistingSpace"
                     select="$Source/preceding-sibling::node()[
                               (
                                 self::comment()
                                 or
                                 self::text()
                               )
                               and
                               generate-id(following-sibling::*[1])
                               = generate-id($Source)
                             ]"/>
       <xsl:copy-of select="$ExistingSpace"/>
       <xsl:if test="not(
                       $ExistingSpace/self::text()[
                         normalize-space(.) != string(.)
                       ]
                     ) and $InnerSimulation">
         <xsl:text> </xsl:text>
       </xsl:if>
     </xsl:when>
     <xsl:when test="normalize-space($Source)
                     != string($Source)">
       <xsl:text> </xsl:text>
     </xsl:when>
   </xsl:choose>
 </xsl:template>
 
 <!--
 
  TRANSFORMATION HELPERS
 
  considerations, limitations, etc.:
  1. the transformations tries to preserve as much of the original XML
     as possible, incl. whitespace text/indentation and comments, but
     at times (corner cases of tricks A. + B. below), this needs to be
     sacrificed, e.g., distorting nice indentation, hence if the
     perfection is the goal:
     - user of the transformation can feed the minimized version of
       the XML (no denormalized/any white-space present)
     - user of the transformation can (re-)pretty-print the outcome
       afterwards
 
  tricks and conventions used:
  A. callable templates only return Result Tree Fragments, which means
     the only operations allowed are those looking at the underlying,
     virtual node-set, and since we need to discern their non-void
     production (i.e. on successful match/es), we use this trick:
     - ensure the template will not propagate any denormalized whitespace
     - inject denormalized whitespace (superfluous space) artificially
       to mark successful production (but see B. below)
     - with the template production, here stored as Var variable,
       we test "normalize-space($Var) != $Var" condition to detect
       non-void production, mainly intended to see whether to emit
       the enclosing element at all (with the goal of not leaving
       superfluous elements behind needlessly)
  B. [extension over A.] to eliminate distorted indentation
     (cf. consideration 1.), additional reuse of these callable
     templates is introduced: the template can recursively call
     itself with a special flag (InnerSimulation) as an oracle to
     see to whether non-void production will ensue (all pre-existing
     denormalized whitespace is forcefully removed in this mode),
     and if positive, all such inner pre-existing whitespace is
     then preserved in this outer=main invocation
  C. [extension over B.] when checking the non-void production
     (via InnerSimulation), beside the injected denormalized whitespace,
     we can also inject particular strings, which the callsite of such
     simulation can, in addition, inspect for paricular string
     occurrences, e.g. to prevent clashes on the production coming
     from multiple sources
  D. not only to honour DRY principle and to avoid inner entropy, it's
     often useful to make callable template bimodal, e.g., when the
     production is generated in the "what's to stay in place" vs.
     "what's to be propagated (combined with previous, effectively
     moved) at this other part of the tree" contexts; for such cases,
     there's usually InverseMode parameter to be assigned true()
     (implicit default) and false(), respectively
  E. the common idiom that emerges is: evaluate simulation value,
     depending on the presence of the "success mark" (cf. A.),
     possibly emit non-simulation value; since it would (likely)
     re-evaluate the simulation anew (wastefully) or perhaps
     this sort of dependency injection can just come handy,
     common transformation helpers below offer InnerPass
     parameter to be optionally passed, either as a string (when
     no-denormalized-space is an internal criterium for the template)
     or, conventionally, the result tree fragment representing the
     output of the template at hand called with a simulation flag
     * established signaling strings accompanying InnerSimulation=true:
       - TRIGGER-MSG ... make the template execution emit messages
                         describing changes being performed
       - TRIGGER-RECURSION
                     ... currently used in the oracle-like evaluation
                         of what's the situation with the sibling
                         elements as a recursion guard so that such
                         nested runs won't revisit the new set of
                         siblings per the respective nested context
 
  -->
 
 <!--
  Source ctxt:    cluster_property_set
  Target ctxt:    cluster_property_set
  Target-inv ctxt:/cib/configuration/(op_defaults|rsc_defaults)
                  [cluster_property_set -> meta_attributes]
  Dependencies:   N/A
  -->
 <xsl:template name="cibtr:ProcessClusterProperties">
   <xsl:param name="Source"/>
   <xsl:param name="InverseMode" select="false()"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessClusterProperties">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InverseMode" select="$InverseMode"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <xsl:for-each select="$Source/node()">
     <xsl:choose>
       <xsl:when test="self::text()">
         <!-- cf. trick A. (consideration 1.) -->
         <xsl:choose>
           <xsl:when test="normalize-space($InnerPass)
                           != $InnerPass
                           and
                           (
                             not(following-sibling::nvpair)
                             or
                             generate-id(following-sibling::nvpair[1])
                             != generate-id(following-sibling::*[1])
                           )">
             <xsl:value-of select="."/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:value-of select="normalize-space(.)"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="self::nvpair">
         <xsl:variable name="Replacement"
                       select="$cibtr:MapClusterProperties/cibtr:replace[
                                 @what = current()/@name
                                 and
                                 (
                                   (
                                     @in-case-of
                                     and
                                     contains(concat('|', @in-case-of, '|'),
                                              concat('|', current()/@value, '|'))
                                   )
                                   or
                                   (
                                     not(@in-case-of)
                                     and
                                     not(
                                       $cibtr:MapClusterProperties/cibtr:replace[
                                         @what = current()/@name
                                         and
                                         @in-case-of
                                         and
                                         contains(concat('|', @in-case-of, '|'),
                                                  concat('|', current()/@value, '|'))
                                       ]
                                     )
                                   )
                                 )
                               ]"/>
         <xsl:if test="$InnerPass = 'TRIGGER-MSG'">
           <xsl:call-template name="cibtr:MapMsg">
             <xsl:with-param name="Context" select="@id"/>
             <xsl:with-param name="Replacement" select="$Replacement"/>
           </xsl:call-template>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="$Replacement
                           and
                           (
                             not(string($Replacement/@with))
                             or
                             $Replacement/@where
                           )">
             <!-- drop (possibly just move over) -->
             <xsl:if test="$Replacement/@where
                           and
                           (
                             (
                               normalize-space($InverseMode)
                               and
                               $Replacement/@where = $InverseMode
                             )
                             or
                             (
                               not(normalize-space($InverseMode))
                               and
                               (true() or count($InverseMode))
                               and
                               not(
                                 $InverseMode/nvpair[
                                   @name = $Replacement/@with
                                 ]
                               )
                               and
                               $Replacement/@where = name($InverseMode/..)
                             )
                           )">
               <xsl:call-template name="cibtr:HelperDenormalizedSpace">
                 <xsl:with-param name="Source" select="."/>
                 <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
               </xsl:call-template>
               <xsl:copy>
                 <xsl:for-each select="@*">
                   <xsl:choose>
                     <xsl:when test="name() = 'name'">
                       <xsl:attribute name="{name()}">
                         <xsl:value-of select="$Replacement/@with"/>
                       </xsl:attribute>
                     </xsl:when>
                     <xsl:when test="string($Replacement/@redefined-as)
                                     and
                                     name() = 'value'">
                       <xsl:attribute name="{name()}">
                         <xsl:value-of select="$Replacement/@redefined-as"/>
                       </xsl:attribute>
                     </xsl:when>
                     <xsl:otherwise>
                       <xsl:copy/>
                     </xsl:otherwise>
                   </xsl:choose>
                 </xsl:for-each>
               </xsl:copy>
             </xsl:if>
           </xsl:when>
           <xsl:when test="$InverseMode"/>
           <xsl:when test="$Replacement">
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:copy>
               <xsl:for-each select="@*">
                 <xsl:choose>
                   <xsl:when test="name() = 'name'">
                     <xsl:attribute name="{name()}">
                       <xsl:value-of select="$Replacement/@with"/>
                     </xsl:attribute>
                   </xsl:when>
                   <xsl:when test="string($Replacement/@redefined-as)
                                   and
                                   name() = 'value'">
                     <xsl:attribute name="{name()}">
                       <xsl:value-of select="$Replacement/@redefined-as"/>
                     </xsl:attribute>
                   </xsl:when>
                   <xsl:otherwise>
                     <xsl:copy/>
                   </xsl:otherwise>
                 </xsl:choose>
               </xsl:for-each>
             </xsl:copy>
           </xsl:when>
           <xsl:otherwise>
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:call-template name="cibtr:HelperIdentity"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="$InverseMode
                       or
                       self::comment()">
         <!-- drop -->
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:HelperIdentity"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:for-each>
 </xsl:template>
 
 <!--
  Source ctxt:    (primitive|template)/instance_attributes
  Target ctxt:    (primitive|template)/instance_attributes
  Target-inv ctxt:N/A
  Dependencies:   N/A
  -->
 <xsl:template name="cibtr:ProcessRscInstanceAttributes">
   <xsl:param name="Source"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessRscInstanceAttributes">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <!-- B: special-casing nvpair -->
   <xsl:for-each select="$Source/node()">
     <xsl:choose>
       <xsl:when test="self::text()">
         <!-- cf. trick A. (consideration 1.) -->
         <xsl:choose>
           <xsl:when test="normalize-space($InnerPass)
                           != $InnerPass
                           and
                           (
                             not(following-sibling::nvpair)
                             or
                             generate-id(following-sibling::nvpair[1])
                             != generate-id(following-sibling::*[1])
                           )">
             <xsl:value-of select="."/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:value-of select="normalize-space(.)"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="self::nvpair">
         <xsl:variable name="Replacement"
                       select="$cibtr:MapResourceInstanceAttributes/cibtr:replace[
                                 @what = current()/@name
                                 and
                                 (
                                   (
                                     @in-case-of
                                     and
                                     contains(concat('|', @in-case-of, '|'),
                                              concat('|', current()/@value, '|'))
                                   )
                                   or
                                   (
                                     @in-case-of-droppable-prefix
                                     and
                                     starts-with(current()/@value,
                                                 @in-case-of-droppable-prefix)
                                     and
                                     not(
                                       contains(current()/@value, ',')
                                     )
                                   )
                                   or
                                   (
                                     not(@in-case-of)
                                     and
                                     not(@in-case-of-droppable-prefix)
                                     and
                                     not(
                                       $cibtr:MapResourceInstanceAttributes/cibtr:replace[
                                         @what = current()/@name
                                         and
                                         (
                                           (
                                             @in-case-of
                                             and
                                             contains(concat('|', @in-case-of, '|'),
                                                      concat('|', current()/@value, '|'))
                                           )
                                           or
                                           (
                                             @in-case-of-droppable-prefix
                                             and
                                             starts-with(current()/@value,
                                                         @in-case-of-droppable-prefix)
                                             and
                                             not(
                                               contains(current()/@value, ',')
                                             )
                                           )
                                         )
                                       ]
                                     )
                                   )
                                 )
                               ]"/>
         <xsl:if test="$InnerPass = 'TRIGGER-MSG'">
           <xsl:call-template name="cibtr:MapMsg">
             <xsl:with-param name="Context" select="@id"/>
             <xsl:with-param name="Replacement" select="$Replacement"/>
           </xsl:call-template>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="$Replacement
                           and
                           not(string($Replacement/@with))">
             <!-- drop (move-over code missing) -->
           </xsl:when>
           <xsl:when test="$Replacement">
             <!-- plain rename -->
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:copy>
               <xsl:for-each select="@*">
                 <xsl:choose>
                   <xsl:when test="name() = 'name'">
                     <xsl:attribute name="{name()}">
                       <xsl:value-of select="$Replacement/@with"/>
                     </xsl:attribute>
                   </xsl:when>
                   <xsl:when test="string($Replacement/@redefined-as)
                                   and
                                   name() = 'value'">
                     <xsl:attribute name="{name()}">
                       <xsl:value-of select="$Replacement/@redefined-as"/>
                     </xsl:attribute>
                   </xsl:when>
                   <xsl:when test="string($Replacement/@in-case-of-droppable-prefix)
                                   and
                                   name() = 'value'">
                     <xsl:attribute name="{name()}">
                       <xsl:value-of select="substring-after(
                                               ., $Replacement/@in-case-of-droppable-prefix
                                             )"/>
                     </xsl:attribute>
                   </xsl:when>
                   <xsl:otherwise>
                     <xsl:copy/>
                   </xsl:otherwise>
                 </xsl:choose>
               </xsl:for-each>
             </xsl:copy>
           </xsl:when>
           <xsl:otherwise>
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:call-template name="cibtr:HelperIdentity"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:HelperIdentity"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:for-each>
   <!-- E: special-casing nvpair -->
 </xsl:template>
 
 <!--
  Source ctxt:    (primitive|template)/meta_attributes
  Target ctxt:    (primitive|template)/meta_attributes
  Target-inv ctxt:N/A
  Dependencies:   N/A
  -->
 <xsl:template name="cibtr:ProcessRscMetaAttributes">
   <xsl:param name="Source"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessRscMetaAttributes">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <!-- B: special-casing nvpair -->
   <xsl:for-each select="$Source/node()">
     <xsl:choose>
       <xsl:when test="self::text()">
         <!-- cf. trick A. (consideration 1.) -->
         <xsl:choose>
           <xsl:when test="normalize-space($InnerPass)
                           != $InnerPass
                           and
                           (
                             not(following-sibling::nvpair)
                             or
                             generate-id(following-sibling::nvpair[1])
                             != generate-id(following-sibling::*[1])
                           )">
             <xsl:value-of select="."/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:value-of select="normalize-space(.)"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="self::nvpair">
         <xsl:variable name="Replacement"
                       select="$cibtr:MapResourceMetaAttributes/cibtr:replace[
                                 @what = current()/@name
                                 and
                                 (
                                   (
                                     @in-case-of
                                     and
                                     contains(concat('|', @in-case-of, '|'),
                                              concat('|', current()/@value, '|'))
                                   )
                                   or
                                   (
                                     not(@in-case-of)
                                     and
                                     not(
                                       $cibtr:MapResourceMetaAttributes/cibtr:replace[
                                         @what = current()/@name
                                         and
                                         (
                                           @in-case-of
                                           and
                                           contains(concat('|', @in-case-of, '|'),
                                                    concat('|', current()/@value, '|'))
                                         )
                                       ]
                                     )
                                   )
                                 )
                               ]"/>
         <xsl:if test="$InnerPass = 'TRIGGER-MSG'">
           <xsl:call-template name="cibtr:MapMsg">
             <xsl:with-param name="Context"
                             select="concat(../../@id,
                                            ' (meta=', ../@id,
                                            ')')"/>
             <xsl:with-param name="Replacement" select="$Replacement"/>
           </xsl:call-template>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="$Replacement
                           and
                           not(string($Replacement/@with))">
             <!-- drop (move-over code missing) -->
           </xsl:when>
           <xsl:when test="$Replacement">
             <!-- plain rename -->
             <xsl:variable name="SimulateFollowingSiblings">
               <!-- prevent generating redundant name-value pairs -->
               <xsl:for-each select="(..|../following-sibling::meta_attributes)[
                                       not(rule)
                                     ]">
                 <xsl:if test="$InnerPass != 'TRIGGER-RECURSION'">
                   <xsl:call-template name="cibtr:ProcessRscMetaAttributes">
                     <xsl:with-param name="Source" select="."/>
                     <xsl:with-param name="InnerSimulation" select="true()"/>
                     <xsl:with-param name="InnerPass" select="'TRIGGER-RECURSION'"/>
                   </xsl:call-template>
                 </xsl:if>
               </xsl:for-each>
             </xsl:variable>
             <xsl:choose>
               <!-- instead of HelperDenormalizedSpace -->
               <xsl:when test="$InnerSimulation">
                 <xsl:value-of select="concat(generate-id(), '@', $Replacement/@with, ' ')"/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:if test="not(
                                 contains($SimulateFollowingSiblings,
                                          concat($Replacement/@with, ' '))
                               )
                               or
                               generate-id()
                               =
                               substring-before($SimulateFollowingSiblings,
                                                concat('@', $Replacement/@with))">
                   <xsl:call-template name="cibtr:HelperDenormalizedSpace">
                     <xsl:with-param name="Source" select="."/>
                     <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
                   </xsl:call-template>
                   <xsl:copy>
                     <xsl:for-each select="@*">
                       <xsl:choose>
                         <xsl:when test="name() = 'name'">
                           <xsl:attribute name="{name()}">
                             <xsl:value-of select="$Replacement/@with"/>
                           </xsl:attribute>
                         </xsl:when>
                         <xsl:when test="string($Replacement/@redefined-as)
                                         and
                                         name() = 'value'">
                           <xsl:attribute name="{name()}">
                             <xsl:value-of select="$Replacement/@redefined-as"/>
                           </xsl:attribute>
                         </xsl:when>
                         <xsl:otherwise>
                           <xsl:copy/>
                         </xsl:otherwise>
                       </xsl:choose>
                     </xsl:for-each>
                   </xsl:copy>
                 </xsl:if>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:when>
           <xsl:otherwise>
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:call-template name="cibtr:HelperIdentity"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:HelperIdentity"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:for-each>
   <!-- E: special-casing nvpair -->
 </xsl:template>
 
 <!--
  Source ctxt:    (primitive|template)/operations/op/instance_attributes
  Target ctxt:    (primitive|template)/operations/op/instance_attributes
  Target-inv ctxt:(primitive|template)/operations/op/meta_attributes
  Dependencies:   ProcessNonattrOpMetaAttributes [inverse only]
  -->
 <xsl:template name="cibtr:ProcessOpInstanceAttributes">
   <xsl:param name="Source"/>
   <xsl:param name="InverseMode" select="false()"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <xsl:variable name="EnclosingTag" select="../../.."/>
 
   <!-- B: special-casing nvpair -->
   <xsl:for-each select="$Source/node()">
     <xsl:choose>
       <xsl:when test="self::text()">
         <!-- cf. trick A. (consideration 1.) -->
         <xsl:choose>
           <xsl:when test="normalize-space($InnerPass)
                           != $InnerPass
                           and
                           (
                             not(following-sibling::nvpair)
                             or
                             generate-id(following-sibling::nvpair[1])
                             != generate-id(following-sibling::*[1])
                           )">
             <xsl:value-of select="."/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:value-of select="normalize-space(.)"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="self::nvpair">
         <xsl:variable name="Replacement"
                       select="$cibtr:MapResourcesOperationInstanceAttributes/cibtr:replace[
                                 @what = current()/@name
                                 and
                                 (
                                   (
                                     @in-case-of
                                     and
                                     contains(concat('|', @in-case-of, '|'),
                                              concat('|', current()/../../@name, '|'))
                                   )
                                   or
                                   (
                                     not(@in-case-of)
                                     and
                                     not(
                                       $cibtr:MapResourcesOperationInstanceAttributes/cibtr:replace[
                                         @what = current()/@name
                                         and
                                         @in-case-of
                                         and
                                         contains(concat('|', @in-case-of, '|'),
                                                  concat('|', current()/../../@name, '|'))
                                       ]
                                     )
                                   )
                                 )
                               ]"/>
         <xsl:if test="$InnerPass = 'TRIGGER-MSG'">
           <xsl:call-template name="cibtr:MapMsg">
             <xsl:with-param name="Context"
                             select="concat(../../@id,
                                            ' (rsc=', $EnclosingTag/@id,
                                            ', meta=', ../@id,
                                            ')')"/>
             <xsl:with-param name="Replacement" select="$Replacement"/>
           </xsl:call-template>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="$Replacement
                           and
                           (
                             not(string($Replacement/@with))
                             or
                             $Replacement/@where
                           )">
             <!-- drop (possibly just move over) -->
             <xsl:variable name="SimulateAttrOverrides">
               <xsl:for-each select="../../../op">
                 <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
                   <xsl:with-param name="Source" select="."/>
                   <xsl:with-param name="InverseMode" select="true()"/>
                   <xsl:with-param name="InnerSimulation" select="true()"/>
                 </xsl:call-template>
               </xsl:for-each>
             </xsl:variable>
             <xsl:if test="$InverseMode
                           and
                           not(
                             contains($SimulateAttrOverrides,
                                      concat(@name, ' '))
                           )">
               <!-- do not override; do not collide with:
                    - newly added from op/@* (see last condition above)
                    - existing - actually subsumed with the previous point
                    - successors sourced like this (see below) -->
               <xsl:variable name="SimulateFollowingSiblingsMeta">
                 <!-- cf. similar handling in ProcessAttrOpMetaAttributes,
                      but this is more convoluted -->
                 <xsl:for-each select="(../following-sibling::meta_attributes
                                        |../../following-sibling::op/meta_attributes)[
                                         not(rule)
                                       ]">
                   <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
                     <xsl:with-param name="Source" select="."/>
                     <xsl:with-param name="InverseMode" select="true()"/>
                     <xsl:with-param name="InnerSimulation" select="true()"/>
                   </xsl:call-template>
                 </xsl:for-each>
               </xsl:variable>
               <xsl:variable name="SimulateFollowingSiblingsInstance">
                 <xsl:for-each select="../following-sibling::instance_attributes[
                                         not(rule)
                                       ]">
                   <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
                     <xsl:with-param name="Source" select="."/>
                     <xsl:with-param name="InverseMode" select="true()"/>
                     <xsl:with-param name="InnerSimulation" select="true()"/>
                   </xsl:call-template>
                 </xsl:for-each>
               </xsl:variable>
               <xsl:if test="$Replacement/@where = 'meta_attributes'
                             and
                             not(
                               $EnclosingTag/meta_attributes[
                                 not(rule)
                                 and
                                 nvpair/@name = $Replacement/@with
                               ]
                             )
                             and
                             not(
                               contains($SimulateFollowingSiblingsInstance,
                                        concat(@name, ' '))
                             )">
                 <!-- cf. trick C. (indicate for inverse mode) -->
                 <xsl:choose>
                   <xsl:when test="$InnerSimulation">
                     <!-- instead of HelperDenormalizedSpace -->
                     <xsl:value-of select="concat(@name, ' ')"/>
                   </xsl:when>
                   <xsl:otherwise>
                     <xsl:call-template name="cibtr:HelperDenormalizedSpace">
                       <xsl:with-param name="Source" select="."/>
                       <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
                     </xsl:call-template>
                     <xsl:copy>
                       <xsl:apply-templates select="@*"
                                            mode="cibtr:main"/>
                     </xsl:copy>
                   </xsl:otherwise>
                 </xsl:choose>
               </xsl:if>
             </xsl:if>
           </xsl:when>
           <xsl:when test="$Replacement">
             <xsl:message terminate="yes">
               <xsl:value-of select="concat('INTERNAL ERROR: ',
                                            $Replacement/../@msg-prefix,
                                            ': no in-situ rename',
                                            ' does not hold (',
                                            not(($InverseMode)), ')')"/>
             </xsl:message>
           </xsl:when>
           <xsl:when test="$InverseMode"/>
           <xsl:otherwise>
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:call-template name="cibtr:HelperIdentity"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="$InverseMode
                       or
                       self::comment()">
         <!-- drop -->
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:HelperIdentity"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:for-each>
   <!-- E: special-casing nvpair -->
 </xsl:template>
 
 <!--
  Source ctxt:    (primitive|template)/operations/op/meta_attributes
                  (primitive|template)/operations/op/instance_attributes (inverse only)
  Target ctxt:    (primitive|template)/operations/op/meta_attributes
  Target-inv ctxt:(primitive|template)/meta_attributes
  Dependencies:   ProcessAttrOpMetaAttributes
                  ProcessNonattrOpMetaAttributes
  -->
 <xsl:template name="cibtr:ProcessNonattrOpMetaAttributes">
   <xsl:param name="Source"/>
   <xsl:param name="InverseMode" select="false()"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <xsl:variable name="EnclosingTag" select="../../.."/>
 
   <xsl:for-each select="$Source/node()">
     <xsl:choose>
       <xsl:when test="self::text()
                       and
                       not($InverseMode)">
         <!-- cf. trick A. (consideration 1.) -->
         <xsl:choose>
           <xsl:when test="normalize-space($InnerPass)
                           != $InnerPass
                           and
                           (
                             not(following-sibling::nvpair)
                             or
                             generate-id(following-sibling::nvpair[1])
                             != generate-id(following-sibling::*[1])
                           )">
             <xsl:value-of select="."/>
           </xsl:when>
           <xsl:otherwise>
             <xsl:value-of select="normalize-space(.)"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="self::nvpair">
         <xsl:variable name="Replacement"
                       select="$cibtr:MapResourcesOperation/cibtr:replace[
                                 @what = current()/@name
                                 and
                                 (
                                   (
                                     @in-case-of
                                     and
                                     contains(concat('|', @in-case-of, '|'),
                                              concat('|', current()/../../@name, '|'))
                                   )
                                   or
                                   (
                                     not(@in-case-of)
                                     and
                                     not(
                                       $cibtr:MapResourcesOperation/cibtr:replace[
                                         @what = current()/@name
                                         and
                                         @in-case-of
                                         and
                                         contains(concat('|', @in-case-of, '|'),
                                                  concat('|', current()/../../@name, '|'))
                                       ]
                                     )
                                   )
                                 )
                               ]"/>
         <xsl:if test="$InnerPass = 'TRIGGER-MSG'">
           <xsl:call-template name="cibtr:MapMsg">
             <xsl:with-param name="Context"
                             select="concat(../../@id,
                                            ' (rsc=', $EnclosingTag/@id,
                                            ', meta=', ../@id,
                                            ')')"/>
             <xsl:with-param name="Replacement" select="$Replacement"/>
           </xsl:call-template>
         </xsl:if>
         <xsl:choose>
           <xsl:when test="$Replacement
                           and
                           (
                             not(string($Replacement/@with))
                             or
                             $Replacement/@where
                           )">
             <!-- drop (possibly just move over) -->
             <xsl:if test="$InverseMode">
               <xsl:variable name="SimulateAttrOverrides">
                 <xsl:for-each select="../../../op">
                   <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
                     <xsl:with-param name="Source" select="."/>
                     <xsl:with-param name="InverseMode" select="true()"/>
                     <xsl:with-param name="InnerSimulation" select="true()"/>
                   </xsl:call-template>
                 </xsl:for-each>
               </xsl:variable>
               <xsl:if test="not(
                               contains($SimulateAttrOverrides,
                                        concat(@name, ' '))
                             )">
                 <!-- do not override; do not collide with:
                      - newly added from op/@* (see last condition above)
                      - existing - actually subsumed with the previous point
                      - successors sourced like this (see below)
                      and if coming from op/instance_attributes, add also
                      - any meta_attributes sourced like this -->
                 <xsl:variable name="SimulateFollowingSiblings">
                   <!-- cf. similar handling in ProcessAttrOpMetaAttributes,
                        but this is more convoluted -->
                   <xsl:if test="name(..) = 'meta_attributes'">
                     <xsl:for-each select="(../following-sibling::meta_attributes
                                            |../../following-sibling::op/meta_attributes)[
                                             not(rule)
                                           ]">
                       <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
                         <xsl:with-param name="Source" select="."/>
                         <xsl:with-param name="InverseMode" select="true()"/>
                         <xsl:with-param name="InnerSimulation" select="true()"/>
                       </xsl:call-template>
                     </xsl:for-each>
                   </xsl:if>
                   <xsl:if test="name(..) = 'instance_attributes'">
                     <xsl:for-each select="(../following-sibling::instance_attributes
                                            |../../following-sibling::op/instance_attributes
                                            |../../meta_attributes
                                            |../../../op/meta_attributes)[
                                             not(rule)
                                           ]">
                       <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
                         <xsl:with-param name="Source" select="."/>
                         <xsl:with-param name="InverseMode" select="true()"/>
                         <xsl:with-param name="InnerSimulation" select="true()"/>
                       </xsl:call-template>
                     </xsl:for-each>
                   </xsl:if>
                 </xsl:variable>
                 <xsl:if test="$Replacement/@where = 'meta_attributes'
                               and
                               not(
                                 $EnclosingTag/meta_attributes[
                                   not(rule)
                                   and
                                   nvpair/@name = $Replacement/@with
                                 ]
                               )
                               and
                               not(
                                 contains($SimulateFollowingSiblings,
                                          concat(@name, ' '))
                               )">
                   <!-- cf. trick C. (indicate for inverse mode) -->
                   <xsl:choose>
                     <!-- instead of HelperDenormalizedSpace -->
                     <xsl:when test="$InnerSimulation">
                       <xsl:value-of select="concat(@name, ' ')"/>
                     </xsl:when>
                     <xsl:otherwise>
                       <xsl:copy>
                         <xsl:apply-templates select="@*"
                                              mode="cibtr:main"/>
                       </xsl:copy>
                     </xsl:otherwise>
                   </xsl:choose>
                 </xsl:if>
               </xsl:if>
             </xsl:if>
           </xsl:when>
           <xsl:when test="$Replacement">
             <xsl:message terminate="yes">
               <xsl:value-of select="concat('INTERNAL ERROR: ',
                                            $Replacement/../@msg-prefix,
                                            ': no in-situ rename',
                                            ' does not hold (',
                                            not(($InverseMode)), ')')"/>
             </xsl:message>
           </xsl:when>
           <xsl:when test="$InverseMode"/>
           <xsl:otherwise>
             <xsl:call-template name="cibtr:HelperDenormalizedSpace">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
             </xsl:call-template>
             <xsl:call-template name="cibtr:HelperIdentity"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:when>
       <xsl:when test="$InverseMode
                       or
                       self::comment()">
         <!-- drop -->
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:HelperIdentity"/>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:for-each>
 </xsl:template>
 
 <!--
  Source ctxt:    (primitive|template)/operations/op
  Target ctxt:    (primitive|template)/operations/op/meta_attributes
  Target-inv ctxt:(primitive|template)/meta_attributes
  Dependencies:   ProcessNonattrOpMetaAttributes [non-inverse only]
                  ProcessOpInstanceAttributes [non-inverse only]
  -->
 <xsl:template name="cibtr:ProcessAttrOpMetaAttributes">
   <xsl:param name="Source"/>
   <xsl:param name="InverseMode" select="false()"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InverseMode" select="$InverseMode"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <xsl:variable name="EnclosingTag" select="../.."/>
 
   <xsl:if test="(
                   $InverseMode
                   and
                   (
                     $InnerSimulation
                     or
                     normalize-space($InnerPass)
                     != string($InnerPass)
                   )
                 )
                 or
                 not($InverseMode)">
     <xsl:if test="$InverseMode
                   and
                   $InnerSimulation">
       <xsl:call-template name="cibtr:HelperDenormalizedSpace">
         <xsl:with-param name="Source" select="$InnerPass"/>
         <xsl:with-param name="ResultTreeFragment" select="true()"/>
       </xsl:call-template>
     </xsl:if>
 
     <!-- cannot combine "copy" with creating a new element, hence we mimic
          "copy" with recreating the element anew, while still using just
          a single for-each loop -->
     <xsl:variable name="ParentName">
       <xsl:choose>
         <xsl:when test="not($InverseMode)">
           <xsl:value-of select="name()"/>
         </xsl:when>
         <xsl:otherwise>
           <xsl:value-of select="'nvpair'"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:variable>
     <xsl:element name="{$ParentName}">
     <!-- B: special-casing @* -->
     <xsl:for-each select="@*">
       <xsl:variable name="Replacement"
                     select="$cibtr:MapResourcesOperation/cibtr:replace[
                               @what = name(current())
                               and
                               (
                                 (
                                   @in-case-of
                                   and
                                   contains(concat('|', @in-case-of, '|'),
                                            concat('|', current()/../@name, '|'))
                                 )
                                 or
                                 (
                                   not(@in-case-of)
                                   and
                                   not(
                                     $cibtr:MapResourcesOperation/cibtr:replace[
                                       @what = name(current())
                                       and
                                       @in-case-of
                                       and
                                       contains(concat('|', @in-case-of, '|'),
                                                concat('|', current()/../@name, '|'))
                                     ]
                                   )
                                 )
                               )
                             ]"/>
       <xsl:if test="$InnerPass = 'TRIGGER-MSG'">
         <xsl:call-template name="cibtr:MapMsg">
           <xsl:with-param name="Context"
                                 select="concat(../@id,
                                                ' (rsc=', $EnclosingTag/@id,
                                                ')')"/>
           <xsl:with-param name="Replacement" select="$Replacement"/>
         </xsl:call-template>
       </xsl:if>
       <xsl:choose>
         <!-- use inner simulation to find out if success,
              then emit also extra denormalized space -->
         <xsl:when test="$InverseMode
                         and
                         $Replacement/@where = 'meta_attributes'
                         and
                         not(
                           $EnclosingTag/meta_attributes[
                             not(rule)
                             and
                             nvpair/@name = $Replacement/@with
                           ]
                         )">
           <!-- do not override; do not collide with:
                - existing (see last condition above)
                - successors sourced like this (see below) -->
           <xsl:variable name="SimulateFollowingSiblings">
             <xsl:for-each select="../following-sibling::op">
               <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
                 <xsl:with-param name="Source" select="."/>
                 <xsl:with-param name="InverseMode" select="true()"/>
                 <xsl:with-param name="InnerSimulation" select="true()"/>
               </xsl:call-template>
             </xsl:for-each>
           </xsl:variable>
           <xsl:if test="not(contains($SimulateFollowingSiblings,
                                      concat(name(), ' ')))">
             <!-- fix concurrent op/@* sources (these themselves are winning
                  over sources from meta_attributes -->
             <xsl:choose>
               <xsl:when test="$InnerSimulation">
                 <!-- cf. trick C. (indicate for inverse mode) -->
                 <xsl:value-of select="concat(name(), ' ')"/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:attribute name="id">
                   <xsl:value-of select="concat('_2TO3_', ../@id, '-meta-',
                                                $Replacement/@with)"/>
                 </xsl:attribute>
                 <xsl:attribute name="name">
                   <xsl:value-of select="$Replacement/@with"/>
                 </xsl:attribute>
                 <xsl:attribute name="value">
                   <xsl:value-of select="."/>
                 </xsl:attribute>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:if>
         </xsl:when>
         <xsl:when test="$InverseMode"/>
         <xsl:when test="$Replacement
                         and
                         (
                           not(string($Replacement/@with))
                           or
                           $Replacement/@where
                         )">
           <!-- drop (possibly just move over) -->
         </xsl:when>
         <xsl:when test="$Replacement">
           <xsl:message terminate="yes">
             <xsl:value-of select="concat('INTERNAL ERROR: ',
                                          $Replacement/../@msg-prefix,
                                          ': no in-situ rename',
                                          ' does not hold')"/>
           </xsl:message>
         </xsl:when>
         <xsl:otherwise>
           <xsl:copy/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:for-each>
     <!-- E: special-casing @* -->
 
     <xsl:if test="not($InverseMode)">
       <!-- Look ahead if there are any meta-like instance_attibutes to
            be propagated next door, into existing/new meta_attributes -->
       <xsl:variable name="ProcessedInverseNonruleOpInstanceAttributes">
         <xsl:for-each select="instance_attributes[not(rule)]">
           <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
             <xsl:with-param name="Source" select="."/>
             <xsl:with-param name="InnerSimulation" select="true()"/>
             <xsl:with-param name="InverseMode" select="true()"/>
             <xsl:with-param name="InnerPass"
                             select="substring-after(
                                       concat(
                                         string($InnerSimulation),
                                         'TRIGGER-MSG'
                                       ),
                                      'true'
                                     )"/>
           </xsl:call-template>
         </xsl:for-each>
       </xsl:variable>
       <!-- B: special-casing instance_attributes|meta_attributes -->
       <xsl:for-each select="$Source/node()">
         <xsl:choose>
           <xsl:when test="self::text()">
             <!-- cf. trick A. (consideration 1.) -->
             <xsl:choose>
               <xsl:when test="normalize-space($InnerPass)
                               != $InnerPass
                               and
                               (
                                 not(following-sibling::nvpair)
                                 or
                                 generate-id(following-sibling::nvpair[1])
                                 != generate-id(following-sibling::*[1])
                               )">
                 <xsl:value-of select="."/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:value-of select="normalize-space(.)"/>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:when>
           <xsl:when test="self::instance_attributes">
             <xsl:variable name="ProcessedOpInstanceAttributes">
               <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
                 <xsl:with-param name="Source" select="."/>
                 <xsl:with-param name="InnerSimulation" select="true()"/>
               </xsl:call-template>
             </xsl:variable>
             <!-- cf. trick A. -->
             <xsl:if test="normalize-space($ProcessedOpInstanceAttributes)
                           != $ProcessedOpInstanceAttributes">
               <xsl:copy>
                 <xsl:apply-templates select="@*"
                                      mode="cibtr:main"/>
                 <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
                   <xsl:with-param name="Source" select="."/>
                   <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
                   <!-- cf. trick E. -->
                   <xsl:with-param name="InnerPass" select="$ProcessedOpInstanceAttributes"/>
                 </xsl:call-template>
               </xsl:copy>
             </xsl:if>
           </xsl:when>
           <xsl:when test="self::meta_attributes">
             <xsl:variable name="ProcessedOpMetaAttributes">
               <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
                 <xsl:with-param name="Source" select="."/>
                 <xsl:with-param name="InnerSimulation" select="true()"/>
                 <xsl:with-param name="InnerPass"
                                 select="substring-after(
                                           concat(
                                             string($InnerSimulation),
                                             'TRIGGER-MSG'
                                           ),
                                          'true'
                                         )"/>
               </xsl:call-template>
             </xsl:variable>
             <!-- cf. trick A.;
                  possibly piggy-back instance_attributes (if any per
                  above look ahead) to first suitable (not rules-driven)
                  meta_attributes set... -->
             <xsl:if test="normalize-space($ProcessedOpMetaAttributes)
                           != $ProcessedOpMetaAttributes
                           or
                           (
                             not(rule)
                             and
                             not(preceding-sibling::meta_attributes[not(rule)])
                             and
                             normalize-space($ProcessedInverseNonruleOpInstanceAttributes)
                             != $ProcessedInverseNonruleOpInstanceAttributes
                           )">
               <xsl:copy>
                 <xsl:apply-templates select="@*"
                                      mode="cibtr:main"/>
                 <xsl:if test="normalize-space($ProcessedOpMetaAttributes)
                               != $ProcessedOpMetaAttributes">
                   <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
                     <xsl:with-param name="Source" select="."/>
                     <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
                     <!-- cf. trick E. -->
                     <xsl:with-param name="InnerPass" select="$ProcessedOpMetaAttributes"/>
                   </xsl:call-template>
                 </xsl:if>
                 <xsl:if test="not(rule)
                               and
                               not(preceding-sibling::meta_attributes[not(rule)])
                               and
                               normalize-space($ProcessedInverseNonruleOpInstanceAttributes)
                               != $ProcessedInverseNonruleOpInstanceAttributes">
                   <xsl:for-each select="../instance_attributes[not(rule)]">
                     <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
                       <xsl:with-param name="Source" select="."/>
                       <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
                       <xsl:with-param name="InverseMode" select="true()"/>
                     </xsl:call-template>
                   </xsl:for-each>
                 </xsl:if>
               </xsl:copy>
             </xsl:if>
           </xsl:when>
           <xsl:otherwise>
             <xsl:call-template name="cibtr:HelperIdentity"/>
           </xsl:otherwise>
         </xsl:choose>
       </xsl:for-each>
       <!-- E: special-casing instance_attributes|meta_attributes -->
 
       <!-- ...or roll out brand new meta_attributes, first collectively
            for no-rules instances... -->
       <xsl:if test="not(meta_attributes[not(rule)])
                     and
                     normalize-space($ProcessedInverseNonruleOpInstanceAttributes)
                     != $ProcessedInverseNonruleOpInstanceAttributes">
         <meta_attributes id="{concat('_2TO3_', @id, '-meta')}">
           <xsl:for-each select="instance_attributes[not(rule)]">
             <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
               <xsl:with-param name="InverseMode" select="true()"/>
             </xsl:call-template>
           </xsl:for-each>
           <xsl:apply-templates select="text()[position() = last()]"
                                mode="cibtr:main"/>
         </meta_attributes>
         <xsl:apply-templates select="text()[position() = last()]"
                              mode="cibtr:main"/>
       </xsl:if>
 
       <!-- ...then individually for rules-driven ones -->
       <xsl:for-each select="instance_attributes[rule]">
         <xsl:variable name="ProcessedInverseRuleOpInstanceAttributes">
           <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
             <xsl:with-param name="Source" select="."/>
             <xsl:with-param name="InnerSimulation" select="true()"/>
             <xsl:with-param name="InverseMode" select="true()"/>
             <xsl:with-param name="InnerPass"
                             select="substring-after(
                                       concat(
                                         string($InnerSimulation),
                                         'TRIGGER-MSG'
                                       ),
                                      'true'
                                     )"/>
           </xsl:call-template>
         </xsl:variable>
         <!-- cf. trick A. -->
         <xsl:if test="normalize-space($ProcessedInverseRuleOpInstanceAttributes)
                       != $ProcessedInverseRuleOpInstanceAttributes">
           <meta_attributes>
             <xsl:apply-templates select="@*[
                                            name() != 'id'
                                          ]"
                                  mode="cibtr:main"/>
             <xsl:attribute name='id'>
               <xsl:value-of select="concat('_2TO3_', @id)"/>
             </xsl:attribute>
             <xsl:apply-templates select="node()[
                                            name() != 'nvpair'
                                          ]"
                                  mode="cibtr:main"/>
             <xsl:call-template name="cibtr:ProcessOpInstanceAttributes">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InverseMode" select="true()"/>
               <!-- cf. trick E. -->
               <xsl:with-param name="InnerPass" select="$ProcessedInverseRuleOpInstanceAttributes"/>
             </xsl:call-template>
             <xsl:apply-templates select="text()[position() = last()]"
                                  mode="cibtr:main"/>
           </meta_attributes>
         </xsl:if>
       </xsl:for-each>
     </xsl:if>
     </xsl:element>
   </xsl:if>
 </xsl:template>
 
 <!--
  Source ctxt:    configuration
  Target ctxt:    {op,rsc}_defaults/meta_attributes [per $Variant, see below]
  Target-inv ctxt:N/A
  Dependencies:   ProcessClusterProperties
 
  Variant:        'op_defaults' | 'rsc_defaults'
  -->
 <xsl:template name="cibtr:ProcessDefaultsNonruleClusterProperties">
   <xsl:param name="Source"/>
   <xsl:param name="Variant"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="Variant" select="$Variant"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <xsl:choose>
     <xsl:when test="$Source/*[name() = $Variant]/meta_attributes[
                       not(@id-ref)
                       and
                       not(rule)
                     ]">
       <xsl:call-template name="cibtr:ProcessClusterProperties">
         <xsl:with-param name="Source"
                         select="$Source/crm_config/cluster_property_set[
                                   not(@id-ref)
                                   and
                                   not(rule)
                                 ]"/>
         <xsl:with-param name="InverseMode"
                         select="$Source/*[name() = $Variant]/meta_attributes[
                                   not(@id-ref)
                                   and
                                   not(rule)
                                 ]"/>
         <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template name="cibtr:ProcessClusterProperties">
         <xsl:with-param name="Source"
                       select="$Source/crm_config/cluster_property_set[
                                   not(@id-ref)
                                   and
                                   not(rule)
                                 ]"/>
         <xsl:with-param name="InverseMode"
                         select="$Variant"/>
         <xsl:with-param name="InnerSimulation" select="$InnerSimulation"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
 
 <!--
  Source ctxt:    configuration
  Target ctxt:    {op,rsc}_defaults/meta_attributes [per $Variant, see below]
  Target-inv ctxt:N/A
  Dependencies:   ProcessClusterProperties
 
  Variant:        'op_defaults' | 'rsc_defaults'
  -->
 <xsl:template name="cibtr:ProcessDefaultsRuleClusterProperties">
   <xsl:param name="Source"/>
   <xsl:param name="Variant"/>
   <xsl:param name="InnerSimulation" select="false()"/>
   <xsl:param name="InnerPass">
     <xsl:choose>
       <xsl:when test="$InnerSimulation">
         <xsl:value-of select="''"/>
       </xsl:when>
       <xsl:otherwise>
         <xsl:call-template name="cibtr:ProcessDefaultsRuleClusterProperties">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="Variant" select="$Variant"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:otherwise>
     </xsl:choose>
   </xsl:param>
 
   <xsl:for-each select="crm_config/cluster_property_set[
                           not(@id-ref)
                           and
                           rule
                         ]">
     <xsl:variable name="ProcessedPartial">
       <xsl:call-template name="cibtr:ProcessClusterProperties">
         <xsl:with-param name="Source" select="$Source"/>
         <xsl:with-param name="InverseMode" select="$Variant"/>
         <xsl:with-param name="InnerSimulation" select="true()"/>
         <xsl:with-param name="InnerPass" select="'TRIGGER-MSG'"/>
       </xsl:call-template>
     </xsl:variable>
     <xsl:if test="normalize-space($ProcessedPartial)
                   != $ProcessedPartial">
       <meta_attributes id="{concat('_2TO3_', @id)}">
         <xsl-copy-of select="rule"/>
         <xsl:call-template name="cibtr:ProcessClusterProperties">
           <xsl:with-param name="Source" select="$Source"/>
           <xsl:with-param name="InverseMode" select="$Variant"/>
         </xsl:call-template>
       </meta_attributes>
     </xsl:if>
   </xsl:for-each>
 </xsl:template>
 
 <!--
 
  ACTUAL TRANSFORMATION
 
  -->
 
 <xsl:template match="cib" mode="cibtr:main">
   <xsl:copy>
     <xsl:apply-templates select="@*"
                          mode="cibtr:main"/>
     <xsl:attribute name="validate-with">
       <xsl:value-of select="concat('pacemaker-', $cibtr:cib-min-ver)"/>
     </xsl:attribute>
     <xsl:apply-templates select="node()"
                          mode="cibtr:main"/>
   </xsl:copy>
 </xsl:template>
 
 <xsl:template match="cluster_property_set" mode="cibtr:main">
   <xsl:variable name="ProcessedClusterProperties">
     <xsl:call-template name="cibtr:ProcessClusterProperties">
       <xsl:with-param name="Source" select="."/>
       <xsl:with-param name="InnerSimulation" select="true()"/>
       <xsl:with-param name="InnerPass" select="'TRIGGER-MSG'"/>
     </xsl:call-template>
   </xsl:variable>
   <xsl:if test="normalize-space($ProcessedClusterProperties)
                 != $ProcessedClusterProperties">
     <xsl:copy>
       <xsl:apply-templates select="@*"
                            mode="cibtr:main"/>
       <xsl:call-template name="cibtr:ProcessClusterProperties">
         <xsl:with-param name="Source" select="."/>
         <!-- cf. trick E. -->
         <xsl:with-param name="InnerPass" select="$ProcessedClusterProperties"/>
       </xsl:call-template>
     </xsl:copy>
   </xsl:if>
 </xsl:template>
 
 <xsl:template match="rsc_colocation" mode="cibtr:main">
   <xsl:copy>
     <xsl:for-each select="@*">
       <xsl:variable name="Replacement"
                     select="$cibtr:MapConstraintsColocation/cibtr:replace[
                               @what = name(current())
                             ]"/>
       <xsl:call-template name="cibtr:MapMsg">
         <xsl:with-param name="Context" select="../@id"/>
         <xsl:with-param name="Replacement" select="$Replacement"/>
       </xsl:call-template>
       <xsl:choose>
         <xsl:when test="$Replacement
                         and
                         not(string($Replacement/@with))">
           <!-- drop -->
         </xsl:when>
         <xsl:when test="$Replacement">
           <!-- rename -->
           <xsl:attribute name="{name()}">
             <xsl:value-of select="$Replacement/@with"/>
           </xsl:attribute>
         </xsl:when>
         <xsl:otherwise>
           <xsl:copy/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:for-each>
     <xsl:apply-templates select="node()"
                          mode="cibtr:main"/>
   </xsl:copy>
 </xsl:template>
 
 <xsl:template match="node" mode="cibtr:main">
   <xsl:copy>
     <xsl:for-each select="@*">
       <xsl:variable name="Replacement"
                     select="$cibtr:MapClusterNode/cibtr:replace[
                               @what = name(current())
                               and
                               (
                                 (
                                   @in-case-of
                                   and
                                   contains(concat('|', @in-case-of, '|'),
                                            concat('|', current(), '|'))
                                 )
                                 or
                                 (
                                   not(@in-case-of)
                                   and
                                   not(
                                     $cibtr:MapClusterNode/cibtr:replace[
                                       @what = name(current())
                                       and
                                       @in-case-of
                                       and
                                       contains(concat('|', @in-case-of, '|'),
                                                concat('|', current(), '|'))
                                     ]
                                   )
                                 )
                               )
                             ]"/>
       <xsl:call-template name="cibtr:MapMsg">
         <xsl:with-param name="Context" select="concat(../@uname, ' (id=', ../@id, ')')"/>
         <xsl:with-param name="Replacement" select="$Replacement"/>
       </xsl:call-template>
       <xsl:choose>
         <xsl:when test="$Replacement
                         and
                         not(string($Replacement/@with))">
           <!-- drop -->
         </xsl:when>
         <xsl:when test="$Replacement">
           <!-- rename -->
           <xsl:attribute name="{$Replacement/@with}">
             <xsl:choose>
               <xsl:when test="$Replacement/@redefined-as">
                 <xsl:value-of select="$Replacement/@redefined-as"/>
               </xsl:when>
               <xsl:otherwise>
                 <xsl:value-of select="."/>
               </xsl:otherwise>
             </xsl:choose>
           </xsl:attribute>
         </xsl:when>
         <xsl:otherwise>
           <xsl:copy/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:for-each>
     <xsl:apply-templates select="node()"
                          mode="cibtr:main"/>
   </xsl:copy>
 </xsl:template>
 
 <!--
  1a. propagate (primitive|template)/operations/
        op[name() = 'start' or name() = 'promote']/@requires
      under new ./meta_attributes/nvpair
 
  1b. "move" (primitive|template)/operations/
        op[name() = 'start' or name() = 'promote']/
        meta_attributes/nvpair[@requires]
      under ./meta_attributes
 
   otherwise, just
 
  2a.  drop (primitive|template)/operations/
         op/@requires
 
  2b.  drop (primitive|template)/operations/
         op/meta_attributes/nvpair[@requires]
 
  Not compatible with meta_attributes referenced via id-ref
  (would need external preprocessing).
  -->
 <xsl:template match="primitive|template" mode="cibtr:main">
   <xsl:copy>
     <xsl:apply-templates select="@*"
                          mode="cibtr:main"/>
     <!-- B: special-casing operations|instance_attributes|meta_attributes -->
     <xsl:for-each select="node()">
       <xsl:choose>
         <xsl:when test="self::operations">
           <xsl:copy>
             <xsl:apply-templates select="@*"
                                  mode="cibtr:main"/>
             <!-- B: special-casing op -->
             <xsl:for-each select="node()">
               <xsl:choose>
                 <xsl:when test="self::op">
                   <!-- process @*|meta_attributes/nvpair
                        (keep/drop/move elsewhere) -->
                   <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
                     <xsl:with-param name="Source" select="."/>
                   </xsl:call-template>
                 </xsl:when>
                 <xsl:otherwise>
                   <xsl:call-template name="cibtr:HelperIdentity"/>
                 </xsl:otherwise>
               </xsl:choose>
             </xsl:for-each>
             <!-- E: special-casing op -->
           </xsl:copy>
         </xsl:when>
         <xsl:when test="self::instance_attributes">
           <xsl:variable name="ProcessedRscInstanceAttributes">
             <xsl:call-template name="cibtr:ProcessRscInstanceAttributes">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="true()"/>
               <xsl:with-param name="InnerPass" select="'TRIGGER-MSG'"/>
             </xsl:call-template>
           </xsl:variable>
           <!-- cf. trick A. -->
           <xsl:if test="normalize-space($ProcessedRscInstanceAttributes)
                         != $ProcessedRscInstanceAttributes">
             <xsl:copy>
               <xsl:apply-templates select="@*"
                                    mode="cibtr:main"/>
               <xsl:call-template name="cibtr:ProcessRscInstanceAttributes">
                 <xsl:with-param name="Source" select="."/>
                 <!-- cf. trick E. -->
                 <xsl:with-param name="InnerPass" select="$ProcessedRscInstanceAttributes"/>
               </xsl:call-template>
             </xsl:copy>
           </xsl:if>
         </xsl:when>
         <xsl:when test="self::meta_attributes">
           <xsl:variable name="ProcessedRscMetaAttributes">
             <xsl:call-template name="cibtr:ProcessRscMetaAttributes">
               <xsl:with-param name="Source" select="."/>
               <xsl:with-param name="InnerSimulation" select="true()"/>
               <xsl:with-param name="InnerPass" select="'TRIGGER-MSG'"/>
             </xsl:call-template>
           </xsl:variable>
           <!-- cf. trick A. -->
           <xsl:if test="normalize-space($ProcessedRscMetaAttributes)
                         != $ProcessedRscMetaAttributes">
             <xsl:copy>
               <xsl:apply-templates select="@*"
                                    mode="cibtr:main"/>
               <xsl:call-template name="cibtr:ProcessRscMetaAttributes">
                 <xsl:with-param name="Source" select="."/>
                 <!-- cf. trick E. -->
                 <xsl:with-param name="InnerPass" select="$ProcessedRscMetaAttributes"/>
               </xsl:call-template>
             </xsl:copy>
           </xsl:if>
         </xsl:when>
         <xsl:otherwise>
           <xsl:call-template name="cibtr:HelperIdentity"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:for-each>
     <!-- E: special-casing operations|instance_attributes|meta_attributes -->
 
     <!-- add as last meta_attributes block... -->
 
     <!-- ...indirectly from op attributes -->
     <xsl:variable name="ToPropagateFromOp">
       <xsl:for-each select="operations/op">
         <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
           <xsl:with-param name="Source" select="."/>
           <xsl:with-param name="InverseMode" select="true()"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
           <xsl:with-param name="InnerPass" select="'TRIGGER-MSG'"/>
         </xsl:call-template>
       </xsl:for-each>
     </xsl:variable>
     <!-- cf. trick A. -->
     <xsl:if test="normalize-space($ToPropagateFromOp)
                   != $ToPropagateFromOp">
       <meta_attributes id="{concat('_2TO3_', @id, '-meta')}">
         <xsl:for-each select="operations/op">
           <xsl:call-template name="cibtr:ProcessAttrOpMetaAttributes">
             <xsl:with-param name="Source" select="."/>
             <xsl:with-param name="InverseMode" select="true()"/>
           </xsl:call-template>
         </xsl:for-each>
         <xsl:apply-templates select="text()[position() = last()]"
                              mode="cibtr:main"/>
       </meta_attributes>
       <xsl:apply-templates select="text()[position() = last()]"
                            mode="cibtr:main"/>
     </xsl:if>
 
     <!-- ...directly by picking existing nvpairs of
          meta_attributes|instance_attributes -->
     <xsl:for-each select="operations/op/meta_attributes
                           |operations/op/instance_attributes">
       <xsl:variable name="ProcessedOpMetaAttributes">
         <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
           <xsl:with-param name="Source" select="."/>
           <xsl:with-param name="InverseMode" select="true()"/>
           <xsl:with-param name="InnerSimulation" select="true()"/>
         </xsl:call-template>
       </xsl:variable>
       <!-- cf. trick A. -->
       <xsl:if test="normalize-space($ProcessedOpMetaAttributes)
                     != $ProcessedOpMetaAttributes">
         <!-- cannot xsl:copy, need to settle on meta_attributes -->
         <meta_attributes>
           <xsl:apply-templates select="@*[
                                          name() != 'id'
                                        ]"
                                mode="cibtr:main"/>
           <xsl:attribute name='id'>
             <xsl:value-of select="concat('_2TO3_', @id)"/>
           </xsl:attribute>
           <xsl:apply-templates select="node()[
                                          name() != 'nvpair'
                                        ]"
                                mode="cibtr:main"/>
           <xsl:call-template name="cibtr:ProcessNonattrOpMetaAttributes">
             <xsl:with-param name="Source" select="."/>
             <xsl:with-param name="InverseMode" select="true()"/>
             <!-- cf. trick E. -->
             <xsl:with-param name="InnerPass" select="$ProcessedOpMetaAttributes"/>
           </xsl:call-template>
           <xsl:apply-templates select="text()[position() = last()]"
                                mode="cibtr:main"/>
         </meta_attributes>
         <xsl:apply-templates select="text()[position() = last()]"
                              mode="cibtr:main"/>
       </xsl:if>
     </xsl:for-each>
   </xsl:copy>
 </xsl:template>
 
 <xsl:template match="configuration" mode="cibtr:main">
   <xsl:variable name="Configuration" select="."/>
   <xsl:variable name="ProcessedOpDefaultsNonruleClusterProperties">
     <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
       <xsl:with-param name="Source" select="$Configuration"/>
       <xsl:with-param name="Variant" select="'op_defaults'"/>
       <xsl:with-param name="InnerSimulation" select="true()"/>
     </xsl:call-template>
   </xsl:variable>
   <xsl:variable name="ProcessedRscDefaultsNonruleClusterProperties">
     <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
       <xsl:with-param name="Source" select="$Configuration"/>
       <xsl:with-param name="Variant" select="'rsc_defaults'"/>
       <xsl:with-param name="InnerSimulation" select="true()"/>
     </xsl:call-template>
   </xsl:variable>
   <xsl:variable name="ProcessedOpDefaultsRuleClusterProperties">
     <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
       <xsl:with-param name="Source" select="$Configuration"/>
       <xsl:with-param name="Variant" select="'op_defaults'"/>
       <xsl:with-param name="InnerSimulation" select="true()"/>
     </xsl:call-template>
   </xsl:variable>
   <xsl:variable name="ProcessedRscDefaultsRuleClusterProperties">
     <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
       <xsl:with-param name="Source" select="$Configuration"/>
       <xsl:with-param name="Variant" select="'rsc_defaults'"/>
       <xsl:with-param name="InnerSimulation" select="true()"/>
     </xsl:call-template>
   </xsl:variable>
 
   <xsl:copy>
     <xsl:apply-templates select="@*"
                          mode="cibtr:main"/>
     <!-- B: special-casing {op,rsc}_defaults -->
     <xsl:for-each select="node()">
       <xsl:choose>
         <xsl:when test="self::op_defaults|self::rsc_defaults">
           <xsl:variable name="WhichDefaults" select="name()"/>
           <xsl:copy>
             <xsl:apply-templates select="@*"
                                  mode="cibtr:main"/>
             <!-- B: special-casing meta_attributes -->
             <xsl:for-each select="node()">
               <xsl:copy>
                 <xsl:choose>
                   <xsl:when test="self::meta_attributes[
                                     not(@id-ref)
                                     and
                                     not(rule)
                                     and
                                     not(
                                       preceding-sibling::meta_attributes[
                                         not(@id-ref)
                                         and
                                         not(rule)
                                       ]
                                     )
                                   ]">
                   <xsl:apply-templates select="@*|node()"
                                        mode="cibtr:main"/>
                     <xsl:if test="$WhichDefaults = 'op_defaults'
                                   or
                                   $WhichDefaults = 'rsc_defaults'">
                       <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
                         <xsl:with-param name="Source" select="$Configuration"/>
                         <xsl:with-param name="Variant" select="$WhichDefaults"/>
                       </xsl:call-template>
                     </xsl:if>
                   </xsl:when>
                   <xsl:otherwise>
                     <xsl:apply-templates select="@*|node()"
                                          mode="cibtr:main"/>
                   </xsl:otherwise>
                 </xsl:choose>
                 <xsl:if test="(
                                 $WhichDefaults = 'op_defaults'
                                 and
                                 normalize-space($ProcessedOpDefaultsRuleClusterProperties)
                                 != $ProcessedOpDefaultsRuleClusterProperties
                               )
                               or
                               (
                                 $WhichDefaults = 'rsc_defaults'
                                 and
                                 normalize-space($ProcessedRscDefaultsRuleClusterProperties)
                                 != $ProcessedRscDefaultsRuleClusterProperties
                               )">
                   <xsl:call-template name="cibtr:ProcessDefaultsRuleClusterProperties">
                     <xsl:with-param name="Source" select="$Configuration"/>
                     <xsl:with-param name="Variant" select="$WhichDefaults"/>
                   </xsl:call-template>
                 </xsl:if>
               </xsl:copy>
             </xsl:for-each>
             <!-- E: special-casing meta_attributes -->
           </xsl:copy>
         </xsl:when>
         <xsl:otherwise>
           <xsl:call-template name="cibtr:HelperIdentity"/>
         </xsl:otherwise>
       </xsl:choose>
     </xsl:for-each>
     <!-- E: special-casing {op,rsc}_defaults -->
     <xsl:if test="not(op_defaults)
                   and
                   (
                     normalize-space($ProcessedOpDefaultsNonruleClusterProperties)
                     != $ProcessedOpDefaultsNonruleClusterProperties
                     or
                     normalize-space($ProcessedOpDefaultsRuleClusterProperties)
                     != $ProcessedOpDefaultsRuleClusterProperties
                   )">
       <op_defaults>
         <xsl:if test="normalize-space($ProcessedOpDefaultsNonruleClusterProperties)
                       != $ProcessedOpDefaultsNonruleClusterProperties">
           <meta_attributes id="{concat('_2TO3_', '-op-defaults')}">
             <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
               <xsl:with-param name="Source" select="$Configuration"/>
               <xsl:with-param name="Variant" select="'op_defaults'"/>
             </xsl:call-template>
           </meta_attributes>
         </xsl:if>
         <xsl:call-template name="cibtr:ProcessDefaultsRuleClusterProperties">
           <xsl:with-param name="Source" select="$Configuration"/>
           <xsl:with-param name="Variant" select="'op_defaults'"/>
         </xsl:call-template>
         <xsl:apply-templates select="text()[position() = last()]"
                              mode="cibtr:main"/>
       </op_defaults>
     </xsl:if>
     <xsl:if test="not(rsc_defaults)
                   and
                   (
                     normalize-space($ProcessedRscDefaultsNonruleClusterProperties)
                     != $ProcessedRscDefaultsNonruleClusterProperties
                     or
                     normalize-space($ProcessedRscDefaultsRuleClusterProperties)
                     != $ProcessedRscDefaultsRuleClusterProperties
                   )">
       <rsc_defaults>
         <xsl:if test="normalize-space($ProcessedRscDefaultsNonruleClusterProperties)
                       != $ProcessedRscDefaultsNonruleClusterProperties">
           <meta_attributes id="{concat('_2TO3_', '-rsc-defaults')}">
             <xsl:call-template name="cibtr:ProcessDefaultsNonruleClusterProperties">
               <xsl:with-param name="Source" select="$Configuration"/>
               <xsl:with-param name="Variant" select="'rsc_defaults'"/>
             </xsl:call-template>
           </meta_attributes>
         </xsl:if>
         <xsl:call-template name="cibtr:ProcessDefaultsRuleClusterProperties">
           <xsl:with-param name="Source" select="$Configuration"/>
           <xsl:with-param name="Variant" select="'rsc_defaults'"/>
         </xsl:call-template>
         <xsl:apply-templates select="text()[position() = last()]"
                              mode="cibtr:main"/>
       </rsc_defaults>
     </xsl:if>
   </xsl:copy>
 </xsl:template>
 
+<!-- used in test files to allow in-browser on-the-fly upgrade reports -->
+<xsl:template match="processing-instruction()[
+                       name() = 'xml-stylesheet'
+                       and
+                       count(..|/) = 1
+                     ]"
+              mode="cibtr:main"/>
+
 <xsl:template match="@*|node()" mode="cibtr:main">
   <xsl:call-template name="cibtr:HelperIdentity"/>
 </xsl:template>
 
 <!-- mode-less, easy to override kick-off -->
 <xsl:template match="/">
   <xsl:call-template name="cibtr:HelperIdentity"/>
 </xsl:template>
 
 </xsl:stylesheet>