问题
I did not have much luck to have a complete answer in my previous post. So I am trying yet again with a different approach.
How would one detect the error in the following docbook article with table:
$ cat article.xml
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<article xmlns="http://docbook.org/ns/docbook" version="5.0">
<title>Title</title>
<table>
<caption>caption</caption>
<tbody>
<tr>
<td rowspan="2">
<para>my para</para>
</td>
</tr>
</tbody>
</table>
</article>
Obviously since I made a small reproducible example I know where the error is in my input docbook document, my question is instead about the command line tools that are available to detect them and tracked them down efficiently (line number and possibly column offset).
I will only accept answer that detect the error either using the input docbook 5.0 (XML) document, or the input formatting-object (FO file).
The answer should be explicit in the series of command line tools (Use software 'X' is not an acceptable answer).
Ideally I would have guess I could simply run:
$ xmllint --nonet --noout --schema /usr/share/xml/docbook/schema/xsd/5.0/docbook.xsd article.xml
article.xml validates
or
$ jing /usr/share/xml/docbook/schema/rng/5.0/docbook.rng article.xml && echo "success"
success
For reference here is all I have on my Debian GNU/Linux system [*]
UPDATE: I am not looking for a general solution to all possible FO issues, I am simply looking for a way to track issue(s) in long and complex <table>
element.
[*]
$ xsltproc -o article.fo /usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl article.xml && fop article.fo article.pdf
Note: namesp. cut : stripped namespace before processing Additional Protocols
Note: namesp. cut : processing stripped document Additional Protocols
Making portrait pages on USletter paper (8.5inx11in)
[WARN] FOUserAgent - The following feature isn't implemented by Apache FOP, yet: table-layout="auto" (on fo:table) (See position 2:30164)
[ERROR] FOP - Exception <org.apache.fop.apps.FOPException: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.>org.apache.fop.apps.FOPException: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:288)
at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:115)
at org.apache.fop.cli.Main.startFOP(Main.java:186)
at org.apache.fop.cli.Main.main(Main.java:217)
Caused by: javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:502)
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:285)
... 3 more
Caused by: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
at org.apache.fop.fo.flow.table.FixedColRowGroupBuilder.endTablePart(FixedColRowGroupBuilder.java:183)
at org.apache.fop.fo.flow.table.VariableColRowGroupBuilder$6.play(VariableColRowGroupBuilder.java:107)
at org.apache.fop.fo.flow.table.VariableColRowGroupBuilder.endTable(VariableColRowGroupBuilder.java:116)
at org.apache.fop.fo.flow.table.Table.finalizeNode(Table.java:260)
at org.apache.fop.fo.FONode.endOfNode(FONode.java:330)
at org.apache.fop.fo.flow.table.Table.endOfNode(Table.java:243)
at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:360)
at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:190)
at org.apache.xalan.transformer.TransformerIdentityImpl.endElement(TransformerIdentityImpl.java:1102)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
at org.apache.xerces.xinclude.XIncludeHandler.endElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:485)
... 4 more
---------
javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:502)
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:285)
at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:115)
at org.apache.fop.cli.Main.startFOP(Main.java:186)
at org.apache.fop.cli.Main.main(Main.java:217)
Caused by: org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
at org.apache.fop.fo.flow.table.FixedColRowGroupBuilder.endTablePart(FixedColRowGroupBuilder.java:183)
at org.apache.fop.fo.flow.table.VariableColRowGroupBuilder$6.play(VariableColRowGroupBuilder.java:107)
at org.apache.fop.fo.flow.table.VariableColRowGroupBuilder.endTable(VariableColRowGroupBuilder.java:116)
at org.apache.fop.fo.flow.table.Table.finalizeNode(Table.java:260)
at org.apache.fop.fo.FONode.endOfNode(FONode.java:330)
at org.apache.fop.fo.flow.table.Table.endOfNode(Table.java:243)
at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:360)
at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:190)
at org.apache.xalan.transformer.TransformerIdentityImpl.endElement(TransformerIdentityImpl.java:1102)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
at org.apache.xerces.xinclude.XIncludeHandler.endElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:485)
... 4 more
---------
org.apache.fop.fo.ValidationException: A table-cell is spanning more rows than available in its parent element.
at org.apache.fop.fo.flow.table.FixedColRowGroupBuilder.endTablePart(FixedColRowGroupBuilder.java:183)
at org.apache.fop.fo.flow.table.VariableColRowGroupBuilder$6.play(VariableColRowGroupBuilder.java:107)
at org.apache.fop.fo.flow.table.VariableColRowGroupBuilder.endTable(VariableColRowGroupBuilder.java:116)
at org.apache.fop.fo.flow.table.Table.finalizeNode(Table.java:260)
at org.apache.fop.fo.FONode.endOfNode(FONode.java:330)
at org.apache.fop.fo.flow.table.Table.endOfNode(Table.java:243)
at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.endElement(FOTreeBuilder.java:360)
at org.apache.fop.fo.FOTreeBuilder.endElement(FOTreeBuilder.java:190)
at org.apache.xalan.transformer.TransformerIdentityImpl.endElement(TransformerIdentityImpl.java:1102)
at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
at org.apache.xerces.xinclude.XIncludeHandler.endElement(Unknown Source)
at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:485)
at org.apache.fop.cli.InputHandler.transformTo(InputHandler.java:285)
at org.apache.fop.cli.InputHandler.renderTo(InputHandler.java:115)
at org.apache.fop.cli.Main.startFOP(Main.java:186)
at org.apache.fop.cli.Main.main(Main.java:217)
回答1:
I propose using XSLT to check for constraints that you define in the XSL file.
I've just prepared such a file for detecting that specific problem you mentioned, which you can run with xsltproc check-tables.xsl article.xml
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:db="http://docbook.org/ns/docbook"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Author: Alberto González Palomo http://sentido-labs.com
2016-12-24 00:20 -->
<!-- BEGIN checks -->
<xsl:template match="db:tbody">
<xsl:variable name="row-count" select="count(db:tr)"/>
<xsl:for-each select=".//db:td[@rowspan]">
<xsl:variable name="last-row-spanned" select="count(parent::db:tr/preceding-sibling::db:tr) + @rowspan"/>
<xsl:if test="$last-row-spanned > $row-count">
<xsl:call-template name="error">
<!-- Optional in this case:
<xsl:with-param name="location" select="."/>
-->
<xsl:with-param name="message">A table-cell is spanning more rows than available in its parent element.</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:for-each>
</xsl:template>
<!-- END checks -->
<xsl:output method="text"/>
<xsl:template match="text()"><!-- Omit text content. --></xsl:template>
<xsl:template name="error">
<xsl:param name="location" select="."/>
<xsl:param name="message">No error message available.</xsl:param>
<!-- To stop at the first error, set the attribute terminate="yes".
In xsltproc, this also causes the process to return a failure value.
-->
<xsl:message terminate="no">
<xsl:text>Error: </xsl:text>
<xsl:call-template name="xpath">
<xsl:with-param name="location" select="$location"/>
</xsl:call-template>
<xsl:text>: </xsl:text>
<xsl:value-of select="$message"/>
</xsl:message>
</xsl:template>
<xsl:template name="xpath">
<xsl:param name="location" select="."/>
<xsl:for-each select="$location/parent::*">
<xsl:call-template name="xpath"/>
</xsl:for-each>
<xsl:text>/</xsl:text>
<xsl:variable name="element-name" select="name($location)"/>
<xsl:value-of select="$element-name"/>
<xsl:variable name="preceding" select="count($location/preceding-sibling::*[name() = $element-name])"/>
<xsl:variable name="following" select="count($location/following-sibling::*[name() = $element-name])"/>
<xsl:if test="$preceding + $following > 0">
<xsl:text>[</xsl:text>
<xsl:value-of select="1 + $preceding"/>
<xsl:text>]</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
The template for "db:tbody"
counts the number of rows available, then iterates over all td
elements that have a @rowspan
attribute and prints an error message if the sum of the element's position and the @rowspan
is greater than the number of tr
rows in the tbody
:
Error:
/article/table/tbody/tr/td
: A table-cell is spanning more rows than available in its parent element.
You can extend it by adding more checks in the "db:tbody"
template or by writing new templates for other elements, and you can modularize it by splitting the templates in separate XSL files and including them with <xsl:import/>
or <xsl:include/>
.
We could of course write a similar program in any other language with XPath support, but you already have an XSLT processor at hand.
来源:https://stackoverflow.com/questions/41123392/detecting-table-element-error-in-docbook-5-0-document