Java 如何在使用ApacheFop呈现的XSL-FO文档中检测溢出或换行

Java 如何在使用ApacheFop呈现的XSL-FO文档中检测溢出或换行,java,xml,sax,xsl-fo,apache-fop,Java,Xml,Sax,Xsl Fo,Apache Fop,我有一个非常简单的FO文档: <?xml version="1.0" encoding="UTF-8"?> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="A4"> <fo:region-body margin-top="30mm" /> &

我有一个非常简单的FO文档:

<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

<fo:layout-master-set>
  <fo:simple-page-master master-name="A4">
    <fo:region-body margin-top="30mm" />
  </fo:simple-page-master>
</fo:layout-master-set>

<fo:page-sequence master-reference="A4">
  <fo:flow flow-name="xsl-region-body">
    <fo:block-container height="10mm" font-size="8mm" overflow="error-if-overflow" wrap-option="wrap">
      <fo:block wrap-option="wrap">Hello W3Schools Hello W3Schools Hello W3Schools sad da sadasd dsaasd</fo:block>
    </fo:block-container>
  </fo:flow>
</fo:page-sequence>
</fo:root>
不幸的是,这是发生错误的
块容器
标记的位置,而不是导致溢出的特定单词。

tl;dr版本: 您可以使用创建生成的页面和区域的XML表示形式,而不是创建PDF输出

然后,您可以将其用作

  • 检查是否发生溢出
  • 检查第一行将放置多少个字符(和/或哪个文本),以便手动修改输入文件
  • 自动重写您的输入文件,以便将溢出的文本放在不同的块中(这将不那么琐碎)

更多详情: 可以使用从命令行创建区域树(AT)输出

fop input.fo -at application/pdf at.xml
或者,您可以使用创建中间格式(IF)输出

fop input.fo -if application/pdf if.xml
(提供了有关如何使用Java代码以编程方式生成中间格式输出的详细信息)

例如,如果您的输入FO文件包含

<!--
there is no need for the wrap-option="wrap" attributes, as that is the default value, 
I added an id attribute on the fo:block-container
-->
<fo:block-container id="foo" height="10mm" font-size="8mm" overflow="error-if-overflow">
  <fo:block>Hello W3Schools Hello W3Schools Hello W3Schools sad da sadasd dsaasd</fo:block>
</fo:block-container>

您好W3学校您好W3学校您好W3学校sad da sadasd dsaasd
IF输出(比AT-one更详细)如下所示:

...
<page index="0" name="1" page-master-name="A4" width="594720" height="792000">
    <page-header/>
    <content>
        <viewport transform="translate(0,85039)" width="594720" height="706961">
            <viewport width="594720" height="28346" clip-rect="0 0 594720 28346">
                <font family="sans-serif" style="normal" weight="400" variant="normal" size="22677" color="#000000"/>
                <id name="foo"/>
                <text x="0" y="19400">Hello W3Schools Hello W3Schools Hello W3Schools sad</text>
                <text x="0" y="46612">da sadasd dsaasd</text>
            </viewport>
        </viewport>
    </content>
    <page-trailer/>
</page>
...
。。。
你好W3学校你好W3学校你好W3学校悲伤
达萨达斯德酒店
...

XPath
//viewport[id[@name='foo']]/text[1]
提供第一行的文本内容。

您的示例包含三个“Hello”。被告知fo:block在“Hello”时坏了,这仍然没有帮助。在一般情况下,溢出前的最后一个“单词”可能不是文本中的“单词”。例如,如果启用了连字符,它可能是“He-”,而且我不知道如果溢出是在LTR块中的一些RTL文本的中间会是什么。如果您根据中断处的单词手动添加中断,您是否能够照顾寡妇和孤儿,例如,当
fo:block
的最后一行溢出时,您是否知道在最后第三行之后在何处中断?我不确定我是否明白您的意图。为了澄清,让我们假设您知道溢出发生在前40个字符之后:您将如何处理此信息?编辑FO文件以删除第40个字符之后的字符?编辑整个块,以便使用少于40个字符说出相同的内容?还有什么吗?@Ifurini我正在处理我的自定义布局(抽象的东西,无论如何都没有连接到XSL-FO),它有可以流动的块。如果我知道溢出发生在第40个字符之后,我将打断文本,使40个字符进入第一个块,其余的字符尝试进入该块的流目标,依此类推。
...
<page index="0" name="1" page-master-name="A4" width="594720" height="792000">
    <page-header/>
    <content>
        <viewport transform="translate(0,85039)" width="594720" height="706961">
            <viewport width="594720" height="28346" clip-rect="0 0 594720 28346">
                <font family="sans-serif" style="normal" weight="400" variant="normal" size="22677" color="#000000"/>
                <id name="foo"/>
                <text x="0" y="19400">Hello W3Schools Hello W3Schools Hello W3Schools sad</text>
                <text x="0" y="46612">da sadasd dsaasd</text>
            </viewport>
        </viewport>
    </content>
    <page-trailer/>
</page>
...