Search code examples
ditaschematron

Add space before inline element with Schematron


I'd like to add spaces before some specific XML inline elements with Schematron, e.g. <ph>, but only if there isn't a space. I cannot see the issue of my rule. Could you please help?

<sch:pattern id="add-space-before-ph">
    <sch:rule context="ph">
        <sch:assert test="preceding::text()[not(ends-with(., ' '))]" 
                    role="warning" 
                    sqf:fix="add-space-before-ph">Add space before &lt;ph&gt;</sch:assert>
        <sqf:fix id="add-space-before-ph">
            <sqf:description>
                <sqf:title>Add space before &lt;ph&gt;</sqf:title>
            </sqf:description>
            <sqf:add position="before" match="." select="' '"/>
        </sqf:fix>
    </sch:rule>
</sch:pattern>

Solution

  • You have two problems with the assert: first problem is that the message is displayed when the assert is not fulfilled so you need to negate its condition, second problem is that you are actually matching a text node with a certain condition instead of checking if the text node fulfills a certain condition so I think the assert should look like this:

    <sch:assert test="ends-with(preceding::text()[1], ' ')" 
                      role="warning" 
                      sqf:fix="add-space-before-ph">Add space before &lt;ph&gt;  </sch:assert> 
    

    And you should also take into account the fact that before the ph there can be more than one spaces + line breaks (XML might be pretty printed)