0
votes

I have the following xml and I would like to unwrap the ph element which is greater than 2.

Input:(xml)

<ul>
 <li>
   <ph>123</ph>
 </li>
 <li>
   <ph>456</ph>
 </li>
 <li>
   <ph>abc</ph>
 </li>
<li>
<ph>xyz</ph>
</li>
</ul>

O/P:

<ul>
 <li>
   <ph>123</ph>
 </li>
 <li>
   <ph>456</ph>
 </li> 
 <li>
abc
 </li>
<li>
xyz
</li>
</ul>

and the below code doesn't work to get the desired output

<sch:pattern>
        <sch:rule context="*/ph" role="error">
            <sch:assert test="not(node()>2)" sqf:fix="unwrap"><sch:name/> element not
                allowed</sch:assert>
            <sqf:fix id="unwrap">
                <sqf:description>
                    <sqf:title>unwrap <sch:name/> element</sqf:title>
                </sqf:description>             
                <sqf:replace select="node()"></sqf:replace>
            </sqf:fix>
        </sch:rule>

Regards, Shil

2
Please add expected output, so that it becomes clearer what the question is. - snwflk
Hi, your conditions are still not clear to me. What do you mean with "greater than"? The element which is unwraped in your result is a string abc which should not compared with a number. - Nico Kutscherauer
It's possible they mean the element index? - snwflk
To get that output, wouldn't you use XSLT? Schematron is for validating a document, but it looks like you want to transform the document, which is what XSLT does. - Joshua Legler
@JoshuaLegler well, that's why Schematron QuickFix (www.schematron-quickfix.com) is used, what's not a bad idea, if the transformations shall be done only for specific lists, selected by a user. If it is a general rule, which should be done always, I'm with you that XSLT is the better solution. - Nico Kutscherauer

2 Answers

0
votes

Ok, assuming that you mean with "greater than 2" the index of the li elements, you could do the following:

  1. Set the context to li[position() gt 2] to get only the li elements with a position greater than 2.
  2. Check if there is a ph element.
  3. Make the unwrap sqf:fix starting from the li element.

The solution would look like this:

    <sch:rule context="li[position() gt 2]">
        <sch:report test="ph" sqf:fix="unwrap">ph element not allowed.</sch:report>
        <sqf:fix id="unwrap">
            <sqf:description>
                <sqf:title>Unwrap ph element.</sqf:title>
            </sqf:description>
            <sqf:replace match="ph" select="node()"/>
        </sqf:fix>
    </sch:rule>

Another way would be, to set the context to ul. In this case you would only get one error message and the QuickFix could do the unwrap at once.

0
votes
 <sch:pattern>
        <sch:rule context="li[position() &gt; 2]">
            <xsl:variable name="offendingph">
                <xsl:for-each select="child::ph">                
                        <xsl:value-of select="node()"/>
               </xsl:for-each>
            </xsl:variable>                    
            <sch:report test="child::ph" sqf:fix="unwrap">ph element not allowed.</sch:report>
            <sqf:fix id="unwrap">
                <sqf:description>
                    <sqf:title>Unwrap ph element.</sqf:title>
                </sqf:description>
                <sqf:replace match="ph" select="$offendingph"/>
            </sqf:fix>
        </sch:rule>
    </sch:pattern>