Default attribute manifestation in Schematron Quick Fixes
This should cover W3C XML Schema, Relax NG and DTD related problems.
-
- Posts: 96
- Joined: Wed Feb 09, 2005 8:57 am
Default attribute manifestation in Schematron Quick Fixes
Validate this DITA topic body on oXygen:
[oxygen]\frameworks\dita\resources\dita-1.2-for-xslt2-other.sch will report the warning "section should only contain one title element" and propose the quick fix to "Convert other titles to text".
If you apply the fix, the elements now look like this:
@class manifests in <b>. It may be technically fine... but still annoying. Is it possible to suppress its manifestation?
I'm writing a similar SQF and looking for how to avoid this behavior.
Code: Select all
<body>
<section>
<title>test</title>
<title><b>test</b></title>
</section>
</body>
If you apply the fix, the elements now look like this:
Code: Select all
<body>
<section>
<title>test</title>
<b class="+ topic/ph hi-d/b ">test</b>
</section>
</body>
I'm writing a similar SQF and looking for how to avoid this behavior.
-
- Posts: 9431
- Joined: Fri Jul 09, 2004 5:18 pm
Re: Default attribute manifestation in Schematron Quick Fixe
Hi,
The quick fix which gets applied in that case looks like:
so it serializes the child content nodes of the second title.
But the XSLT stylesheet template which gets applied on the XML to produce the replacement content will receive the original XML with all default attributes (class for example) expanded by default so they will also be inserted in the actual content when the quick fix is applied.
I will add an issue on our side to find a solution for this.
In the meantime a slightly complicated workaround would be this one:
1) In the Schematron file on the root element declare the XSLT namespace mapping:
2) On the first level inside the Schematron root element add this XSLT template:
3) In the pattern which matches multiple section titles add a variable which calls that template to serialize the content and call that variable from the quick fix like:
Regards,
Radu
The quick fix which gets applied in that case looks like:
Code: Select all
<sqf:replace match="*[contains(@class, ' topic/title ')][position() > 1]" select="child::node()"/>
But the XSLT stylesheet template which gets applied on the XML to produce the replacement content will receive the original XML with all default attributes (class for example) expanded by default so they will also be inserted in the actual content when the quick fix is applied.
I will add an issue on our side to find a solution for this.
In the meantime a slightly complicated workaround would be this one:
1) In the Schematron file on the root element declare the XSLT namespace mapping:
Code: Select all
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
Code: Select all
<xsl:template match="node() | @*" mode="noClass">
<xsl:copy>
<xsl:apply-templates select="@* except @class" mode="noClass"/>
<xsl:apply-templates select="node()" mode="noClass"/>
</xsl:copy>
</xsl:template>
Code: Select all
<pattern id="multiple_section_titles">
...................
<sqf:fix id="convertTitles">
<sqf:description>
<sqf:title>Convert other titles to text</sqf:title>
</sqf:description>
<xsl:variable name="serialized">
<xsl:apply-templates select="*[contains(@class, ' topic/title ')][position() > 1]/child::node()" mode="noClass"/>
</xsl:variable>
<sqf:replace match="*[contains(@class, ' topic/title ')][position() > 1]" select="$serialized"/>
</sqf:fix>
................
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
-
- Posts: 96
- Joined: Wed Feb 09, 2005 8:57 am
Re: Default attribute manifestation in Schematron Quick Fixe
It worked. Ideally I'd prefer something global like Saxon -expand option. But hardcoding to remove @class will do in my current use case. Thank you for the practical workaround.
-
- Posts: 9431
- Joined: Fri Jul 09, 2004 5:18 pm
Re: Default attribute manifestation in Schematron Quick Fixe
Hi,
The problem with setting an -expand option to the processor would be that your Schematron would no longer be able to properly match in its rules and asserts DITA elements by their class values.
So in a way we need default attribute expansion because we want to properly match DITA element no matter what specialization they have but when serializing XML nodes back to content in a quick fix we want to avoid serializing certain attributes.
One possibility I was thinking of was something would have been to support something like this:
which if supported would instruct the XSLT templates created from the quick fix not to serialize the @class attribute.
Regards,
Radu
The problem with setting an -expand option to the processor would be that your Schematron would no longer be able to properly match in its rules and asserts DITA elements by their class values.
So in a way we need default attribute expansion because we want to properly match DITA element no matter what specialization they have but when serializing XML nodes back to content in a quick fix we want to avoid serializing certain attributes.
One possibility I was thinking of was something would have been to support something like this:
Code: Select all
<sqf:replace match="*[contains(@class, ' topic/title ')][position() > 1]" select="child::node()" ignore-attributes="class"/>
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
<oXygen/> XML Editor
http://www.oxygenxml.com
-
- Posts: 280
- Joined: Thu Nov 28, 2013 9:32 am
- Location: Hamburg/Germany
- Contact:
Re: Default attribute manifestation in Schematron Quick Fixe
Hi,
an alternative might be not to expand the default attributes but access them from the schema. I implement a function for that:
This function works only with saxon and might be limited to xsd. Also I didn't test that from within schematron/sqf, yet.
Reragds,
Patrik
an alternative might be not to expand the default attributes but access them from the schema. I implement a function for that:
Code: Select all
<xsl:function name="my:GetAttributeDefaultValue" as="xs:string?">
<xsl:param name="Element" as="element()"/>
<xsl:param name="AttributeName" as="xs:string"/>
<xsl:variable name="TypeFct" as="function(*)" select="saxon:type($Element)"/>
<xsl:variable name="AttributeUseFct" as="function(*)?" select="$TypeFct('attribute uses')[.('attribute declaration')('name') = $AttributeName]"/>
<xsl:if test="exists($AttributeUseFct)">
<xsl:variable name="UseDefaultFct" as="function(*)?" select="$AttributeUseFct('value constraint')[.('variety') = ('fixed', 'default')]"/>
<xsl:choose>
<xsl:when test="exists($UseDefaultFct)">
<xsl:value-of select="$UseDefaultFct('value')"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="AttributeDeclFct" as="function(*)?" select="$AttributeUseFct('attribute declaration')"/>
<xsl:variable name="DeclDefaultFct" as="function(*)?" select="$AttributeDeclFct('value constraint')[.('variety') = ('fixed', 'default')]"/>
<xsl:if test="exists($DeclDefaultFct)">
<xsl:value-of select="$DeclDefaultFct('value')"/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:function>
Reragds,
Patrik
-
- Posts: 280
- Joined: Thu Nov 28, 2013 9:32 am
- Location: Hamburg/Germany
- Contact:
Re: Default attribute manifestation in Schematron Quick Fixe
There's yet another approach that I used successfully and to keep default attributes from the output and that works with any schema (dtd, xsd or rng):
Regards,
Patrik
- Load the input document without expanding default attributes into a seperate variable.
- Create an xpath expression to the node you want to process.
- Apply this xpath to the variable from step 1.
- Use that result for as input rather than the current one.
Code: Select all
<xsl:variable
name = "documentWithoutDefaultAttributes"
as = "document-node()"
xmlns:jdb = "java:javax.xml.parsers.DocumentBuilder"
xmlns:jdbf = "java:javax.xml.parsers.DocumentBuilderFactory">
<xsl:variable
name = "javaDocBuilderFactory"
as = "jt:javax.xml.parsers.DocumentBuilderFactory"
select = "jdbf:newInstance()"/>
<xsl:variable
name = "javaDocBuilder"
as = "jt:javax.xml.parsers.DocumentBuilder"
select = "jdbf:newDocumentBuilder($javaDocBuilderFactory)"/>
<xsl:sequence select="jdb:parse($javaDocBuilder, base-uri())"/>
</xsl:variable>
Patrik
-
- Posts: 96
- Joined: Wed Feb 09, 2005 8:57 am
Re: Default attribute manifestation in Schematron Quick Fixe
Interesting approach. After adding a few more jdbf:setFeature() to disable loading DTD, it worked. Thanks for sharing it.
The catch is that the document at base-uri() must be in sync with the in-memory one.
The catch is that the document at base-uri() must be in sync with the in-memory one.
Jump to
- Oxygen XML Editor/Author/Developer
- ↳ Feature Request
- ↳ Common Problems
- ↳ DITA (Editing and Publishing DITA Content)
- ↳ SDK-API, Frameworks - Document Types
- ↳ DocBook
- ↳ TEI
- ↳ XHTML
- ↳ Other Issues
- Oxygen XML Web Author
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Content Fusion
- ↳ Feature Request
- ↳ Common Problems
- Oxygen JSON Editor
- ↳ Feature Request
- ↳ Common Problems
- Oxygen PDF Chemistry
- ↳ Feature Request
- ↳ Common Problems
- Oxygen Feedback
- ↳ Feature Request
- ↳ Common Problems
- Oxygen XML WebHelp
- ↳ Feature Request
- ↳ Common Problems
- XML
- ↳ General XML Questions
- ↳ XSLT and FOP
- ↳ XML Schemas
- ↳ XQuery
- NVDL
- ↳ General NVDL Issues
- ↳ oNVDL Related Issues
- XML Services Market
- ↳ Offer a Service