XSL/FO:在“fo:block”上遇到无效属性:在将 html 转换为 PDF (xhmtml2fo) 时显示(没有可用的上下文信息)

Posted

技术标签:

【中文标题】XSL/FO:在“fo:block”上遇到无效属性:在将 html 转换为 PDF (xhmtml2fo) 时显示(没有可用的上下文信息)【英文标题】:XSL/FO: Invalid property encountered on "fo:block": display (No context info available) while converting html to PDF (xhmtml2fo) 【发布时间】:2020-01-13 03:56:06 【问题描述】:

我正在使用将 html 转换为 PDF 的 XSL/FO 生成 PDF。

我正在使用 XSL/FO 样式表,它会生成一个 .fo 文件。 Apache FOP 从 .fo 文件生成一个 pdf。

在我的 html 文件中有很多包含“显示”内联 css 属性的标签,因为出现以下错误:

javax.xml.transform.TransformerException: org.xml.sax.SAXParseException; systemId:文件:/E:/Projects/PDF/xhtml2fo.xsl;行号:484;列号:44;在“fo:block”上遇到无效属性:显示(没有可用的上下文信息)

原因:org.apache.fop.fo.ValidationException:在“fo:block”上遇到无效属性:显示(没有可用的上下文信息) 在 org.apache.fop.events.ValidationExceptionFactory.createException(ValidationExceptionFactory.java:38) 在 org.apache.fop.events.EventExceptionManager.throwException(EventExceptionManager.java:58) 在 org.apache.fop.events.DefaultEventBroadcaster$1.invoke(DefaultEventBroadcaster.java:173) 在 com.sun.proxy.$Proxy65.invalidProperty(未知来源) 在 org.apache.fop.fo.PropertyList.handleInvalidProperty(PropertyList.java:557) 在 org.apache.fop.fo.PropertyList.convertAttributeToProperty(PropertyList.java:476) 在 org.apache.fop.fo.PropertyList.addAttributesToList(PropertyList.java:386) 在 org.apache.fop.fo.FObj.processNode(FObj.java:124) 在 org.apache.fop.fo.FOTreeBuilder$MainFOHandler.startElement(FOTreeBuilder.java:291) 在 org.apache.fop.fo.FOTreeBuilder.startElement(FOTreeBuilder.java:179) 在 org.apache.xalan.transformer.ResultTreeHandler.flushElem(ResultTreeHandler.java:860) ... 72 更多

带有显示属性的html代码:

<div id="something" style="display:block;">Some value</div>

我们如何在 xsl 中包含“显示”样式的部分处理:

<xsl:template name="process-style">

【问题讨论】:

为了让任何人帮助您,您需要包含用于生成 xsl-fo 的 xslt。我假设(基于阅读你的问题)你正在做一些事情,比如将每个 div 变成一个 fo 块,并复制属性,不幸的是,在 fo 块上不允许使用 style 属性,因此你不能这样做。相反,您必须以不同的方式设置所有 fo 元素的样式。 感谢您的回复。我可以包含 xsl 但不能包含 xslt。与从 HTML 转换 PDF 的过程一样,xslt 是在过程中间生成的(并且不能存储)。您能否详细说明“以不同方式设置所有 fo 元素的样式”,这确实会有所帮助。 好的,那么我认为您不在正确的组中。无论您使用什么工具从结构中生成 xslt,您都应该将您的问题标记为关于并询问与该工具相关的问题。我将把这个问题标记为当前形式不可挽救。尝试再次询问您生成 xslt 然后生成 xsl-fo 的工具。 也许您使用的 XSL 会分开并按原样使用属性。属性“display”不是有效的 XSL FO。不超过“-moz-border-radius”是有效的。您需要找到将 CSS 样式转换为“有效”XSL FO 的 XSL。 【参考方案1】:

也许这可以帮助您整理出适合您的软件包。网上有一个应用程序http://www.cloudformatter.com/CSS2Pdf。

此应用程序可在现有浏览器中提取 &lt;div&gt;&lt;div&gt;,并从所有来源解析所有 CSS,将其构建为 XML 并发送到格式。作为该格式的一部分,是一个将内容转换为 XSL FO 的 XSL。 XSL 就在这里。

http://xep.cloudformatter.com/doc/XSL/xeponline-fo-translate-2.xsl

如果您查看此 XSL(是的,它是 1.0,并且在 2.0 中可能更有效),您会发现所有 style 属性被递归解析以分解然后创建 XSL FO 属性的部分来自他们。

从第 1593 行开始:

<xsl:template name="processCSSStyle">
    <xsl:param name="cssString"/>
    <xsl:param name="type"/>
    <xsl:param name="float"/>
    <xsl:param name="ignoreHeight"/>
    <xsl:call-template name="processCSSEntry">
      <xsl:with-param name="attr" select="normalize-space(substring-before($cssString, ': '))"/>
      <xsl:with-param name="value"
        select="normalize-space(substring-after(substring-before($cssString, '; '), ': '))"/>
      <xsl:with-param name="cssRemaining" select="substring-after($cssString, '; ')"/>
      <xsl:with-param name="type" select="$type"/>
      <xsl:with-param name="float" select="$float"/>
      <xsl:with-param name="ignoreHeight" select="$ignoreHeight"/>
    </xsl:call-template>
  </xsl:template>

查看style 中的 CSS 样式列表。

<xsl:template name="processCSSEntry">
    <xsl:param name="attr"/>
    <xsl:param name="value"/>
    <xsl:param name="cssRemaining"/>
    <xsl:param name="type"/>
    <xsl:param name="float"/>
    <xsl:param name="ignoreHeight"/>
    <xsl:if test="$attr">
      <xsl:call-template name="handleAttr">
        <xsl:with-param name="attr" select="$attr"/>
        <xsl:with-param name="value" select="$value"/>
        <xsl:with-param name="type" select="$type"/>
        <xsl:with-param name="float" select="$float"/>
        <xsl:with-param name="ignoreHeight" select="$ignoreHeight"/>
      </xsl:call-template>
      <xsl:call-template name="processCSSEntry">
        <xsl:with-param name="attr" select="normalize-space(substring-before($cssRemaining, ': '))"/>
        <xsl:with-param name="value"
          select="normalize-space(substring-after(substring-before($cssRemaining, '; '), ': '))"/>
        <xsl:with-param name="cssRemaining" select="substring-after($cssRemaining, '; ')"/>
        <xsl:with-param name="type" select="$type"/>
        <xsl:with-param name="float" select="$float"/>
        <xsl:with-param name="ignoreHeight" select="$ignoreHeight"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

最终,这些单独的事情在选择/何时结构中进行处理,如下所示:

  <xsl:when test="$attr = 'margin-left'">
    <xsl:attribute name="margin-left">
      <xsl:value-of select="$value"/>
    </xsl:attribute>
  </xsl:when>

因此,它将style 属性分解为它的组件并制作XSL FO 属性。

我不会发布更多内容,因为您可以下载并检查 XSL。因为它来自浏览器内容,所以这里应用了许多规则,这些规则可能与去除 XSL FO 中没有意义的属性以及对 XSL FO 和 HTML 不同区域的非常具体的处理无关。

【讨论】:

以上是关于XSL/FO:在“fo:block”上遇到无效属性:在将 html 转换为 PDF (xhmtml2fo) 时显示(没有可用的上下文信息)的主要内容,如果未能解决你的问题,请参考以下文章

xsl:fo 在一个块中使用不同的颜色/字体

XSL FO 在具体注释之后读取第一个 fo:table 节点

FOP: fo:block width 属性被忽略?

XSL-FO: fo:marker 可以用来存储任何东西吗?

如何隐藏Xsl Fo上的标题,页面溢出

XSL/FO 在选择语句中跳过一个值