How to exclude namespace (re)declarations in Schematron Quick fixes

This should cover W3C XML Schema, Relax NG and DTD related problems.
fred_a
Posts: 3
Joined: Wed Jul 09, 2025 1:35 pm

How to exclude namespace (re)declarations in Schematron Quick fixes

Post by fred_a »

I'm working with XML documents that have the relevant namespaces declared solely on the root element, and (for mostly stylistic reasons) I'd like to retain that.

When a schematron quick fix containing an xsl template operates on a fragment within the document, the XSLT processor will insert a (redundant) xmlns="..." declaration onto descendants of the element being replaced, thus ignoring the declarations already present in the broader, original document context.

Are there any methods that can be used to avoid this behaviour?

Here's a simplified example to reproduce the behaviour:

Input XML:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<article xmlns:xlink="http://www.w3.org/1999/xlink">
<fig>
<caption>
<p>This is the title <ext-link ext-link-type="uri" xlink:href="https://schematron.com/">link</ext-link>.</p>
<p>This is the caption.</p>
</caption>
</fig>
</article>
Schematron:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<schema
   xmlns="http://purl.oclc.org/dsdl/schematron"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:sqf="http://www.schematron-quickfix.com/validator/process"
   queryBinding="xslt3">
    
    <xsl:template match="." mode="customCopy">
        <xsl:copy copy-namespaces="no">
            <xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()" mode="customCopy"/>
        </xsl:copy>
    </xsl:template>
    
    <sqf:fixes>
        <sqf:fix id="replace-p-to-title">
            <sqf:description>
                <sqf:title>Change the p to title</sqf:title>
            </sqf:description>
            <sqf:replace match="./p[1]">
                <xsl:element name="title">
                    <xsl:apply-templates select="node()|comment()|processing-instruction()" mode="customCopy"/>
                </xsl:element>
            </sqf:replace>
        </sqf:fix>
    </sqf:fixes>
    
    <pattern id="fig">
        <rule context="fig/caption" id="fig-caption-checks">
            <report test="not(title) and (count(p) gt 1)" 
                role="warning" 
                sqf:fix="replace-p-to-title"
                id="fig-caption-1">Caption for fig doesn't have a title, but there are mutliple paragraphs. Is the first paragraph actually the title?</report>
        </rule>
    </pattern>
    
</schema>
Output after fix:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<article xmlns:xlink="http://www.w3.org/1999/xlink">
<fig>
<caption>
<title>This is the title <ext-link ext-link-type="uri" xlink:href="https://schematron.com/" xmlns:xlink="http://www.w3.org/1999/xlink">link</ext-link>.</title>
<p>This is the caption.</p>
</caption>
</fig>
</article>
Note the xmlns:xlink="http://www.w3.org/1999/xlink" declaration on the new title element.

I'm working with oXygen XML Editor version 26.
tavy
Posts: 391
Joined: Thu Jul 01, 2004 12:29 pm

Re: How to exclude namespace (re)declarations in Schematron Quick fixes

Post by tavy »

This is not an Oxygen issue; it's more of an XSLT issue. The copy template will always add the namespace declaration to the result element. I don't think there's any way to avoid this. If you create an XSLT with a copy template, you will get the same result.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xlink="http://www.w3.org/1999/xlink" exclude-result-prefixes="xlink" version="3.0">

<xsl:template match="p">
<xsl:element name="title">
<xsl:apply-templates mode="customCopy" select="node()"/>
</xsl:element>
</xsl:template>

<xsl:template match="node() | @*" mode="customCopy">
<xsl:copy copy-namespaces="false">
<xsl:apply-templates select="node() | @*" mode="customCopy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
In Oxygen, you can avoid adding this namespace declaration if you use the quick fix option in the Author page. In this case, post-processing is performed to remove the namespace declaration when the namespace is already declared on the root element.
Octavian Nadolu
<oXygen/> XML Editor
http://www.oxygenxml.com
fred_a
Posts: 3
Joined: Wed Jul 09, 2025 1:35 pm

Re: How to exclude namespace (re)declarations in Schematron Quick fixes

Post by fred_a »

That makes sense, and good to know about the Author mode trick.

Sounds like I have a couple of options (use author mode and/or do my own post-processing), or I can just stop being so picky.

Thanks very much for your time looking into this.
george
Site Admin
Posts: 2096
Joined: Thu Jan 09, 2003 2:58 pm

Re: How to exclude namespace (re)declarations in Schematron Quick fixes

Post by george »

Hi Fred,

I discussed with Octavian to see what can be done and it turns out we do perform a namespace normalization in the sense of removing unnecessary namespace declarations, but only on the root element that is inserted, not deep on any element. Thus, if you add the in-scope namespaces on the element that you want to insert, that will solve your problem 🙂. The namespaces will not be declared again inside the fragment, because they are already declared on the root element of the fragment, and the ones from the root element will be normalized on insertion.

So, instead of

Code: Select all

           <sqf:replace match="./p[1]" >
                <xsl:element name="title">
                    <xsl:apply-templates select="node() | comment() | processing-instruction()"
                        mode="customCopy"/>
                </xsl:element>
            </sqf:replace>

--- use -->

Code: Select all

           <sqf:replace match="./p[1]" >
                <xsl:element name="title">
                    <xsl:copy-of select="namespace-node()"/>
                    <xsl:apply-templates select="node() | comment() | processing-instruction()"
                        mode="customCopy"/>
                </xsl:element>
            </sqf:replace>

Best Regards,
George
George Cristian Bina
fred_a
Posts: 3
Joined: Wed Jul 09, 2025 1:35 pm

Re: How to exclude namespace (re)declarations in Schematron Quick fixes

Post by fred_a »

Hi George,

Many thanks for this - very helpful, it solves my use-case. After scratching my head for a while, not understanding why it worked in the sample file but not in my real implementation, I realised that the inclusion of schematron namespace declaration interfered:

Code: Select all

<schema xmlns="http://purl.oclc.org/dsdl/schematron">
...
<ns uri="http://www.w3.org/1999/xlink" prefix="xlink"/>
...
Removing this from the schema (and using a wildcard prefix where required) solved the issue. Just mentioning in case this is helpful for anyone else.

Thanks once again for your time in helping me with this.

All the best,
Fred
Post Reply