【问题标题】:XSL Error with Apache FOP in JavaJava 中 Apache FOP 的 XSL 错误
【发布时间】:2014-04-15 02:42:04
【问题描述】:

我花了一天时间寻找解决这个错误的方法,但没有其他主题能真正接近解决同样的问题,更不用说解决它了。所以,如果这是一个重复的问题,我提前道歉。

我们有一个应用程序,它允许用户将图像保存到我们的后端数据存储并从中检索图像。我们还允许他们在图像中包含元数据(称为注释)。对于 TIFF 图像,当用户检索图像时,我们也会检索注释(在 XML 中)。我们使用 Apache FOP 将文本格式化为表格,然后将其呈现为 PNG 文件并与 TIFF 一起显示。

这直到最近才有效。我现在在调用将 XML 转换为 PNG 文件时看到以下错误:

SXCH0003: org.apache.fop.fo.ValidationException: "fo:table-body" 是 缺少子元素。所需内容模型:标记 "fo:table-body" 缺少子元素。必需的 内容模型:marker* (table-row+|table-cell+) (见位置 )

起初我们认为这是一个数据问题,由源 XML 中的空元素/属性引起。我添加了将占位符值强制到 XML 中丢失的任何位置的代码。当这并没有解决问题时,人们相信 XSL(不是我写的)很可能是问题的根源。

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" 
   xmlns:fo="http://www.w3.org/1999/XSL/Format" 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:myns="http://xmlapp.fm.net/ns/app/service">

   <xsl:template match="/">
      <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
          <fo:layout-master-set>
            <fo:simple-page-master master-name="main">
               <fo:region-body margin-top="1cm" margin-bottom="1cm" />
               <fo:region-before extent="0.5cm" />
               <fo:region-after region-name="xsl-region-after" display-align="before" extent="2.0cm"/>
            </fo:simple-page-master>
         </fo:layout-master-set>

          <fo:page-sequence master-reference="main">
            <fo:static-content flow-name="xsl-region-before">
               <fo:block>Page title text</fo:block>
            </fo:static-content>
            <fo:static-content flow-name="xsl-region-after" >
               <fo:block-container left="500pt" top="28pt" width="220mm" position="absolute">
                  <fo:block font-size="16"><xsl:value-of select="//myns:cust" /> : <xsl:value-of select="//myns:docId" /></fo:block>
               </fo:block-container>
            </fo:static-content>
            <fo:flow flow-name="xsl-region-body" >
               <xsl:call-template name="annotationsTable" />
            </fo:flow>
         </fo:page-sequence>
       </fo:root>
   </xsl:template>

   <xsl:template name="annotationsTable">
      <fo:table table-layout="fixed">
         <fo:table-header>
            <fo:table-row>
               <fo:table-cell><fo:block> Annotation </fo:block></fo:table-cell>
               <fo:table-cell><fo:block> UserName </fo:block></fo:table-cell>
               <fo:table-cell><fo:block> UserID </fo:block></fo:table-cell>
               <fo:table-cell><fo:block> Date </fo:block></fo:table-cell>
            </fo:table-row>
         </fo:table-header>
         <fo:table-body>
            <xsl:apply-templates select="//myns:annotation" />
         </fo:table-body>
      </fo:table>
   </xsl:template>

    <xsl:template match="myns:annotation">
      <fo:table-row>
         <fo:table-cell>
            <fo:block>
               <xsl:value-of select="./myns:text" />
            </fo:block>
         </fo:table-cell>
         <fo:table-cell>
            <fo:block>
               <xsl:value-of select="./@createdByName"/>
            </fo:block>
         </fo:table-cell>
         <fo:table-cell>
            <fo:block>
               <xsl:value-of select="./@createdByUserID" />
            </fo:block>
         </fo:table-cell>
         <fo:table-cell>
            <fo:block>
               <xsl:value-of select="./@systemDate" />
            </fo:block>
         </fo:table-cell>
      </fo:table-row>
   </xsl:template>

</xsl:stylesheet>

我们尝试转换的 XML 格式是:

<annotation createdByName="Frank" createdByUserID="X1234" systemDate="2014-04-14">
   <text>this is the text of an annotation</text>
</annotation>

我知道我做错了什么。问题是我对 XSL 的了解不够多,无法知道是什么。有人可以建议吗?

谢谢。

【问题讨论】:

    标签: java xslt sax apache-fop


    【解决方案1】:

    您的代码无法正常工作,因为 XPath 表达式没有选择您在 no-namespace 中的源,试图匹配 http://xmlapp.fm.net/ns/app/service 命名空间中的元素。解决方案是在源代码中将该命名空间声明为默认名称(添加xmlns 属性)或修复 XSLT 中的表达式,使其匹配 no-namespace

    1) 要修复它更改 XSLT,请从 XPath 元素中删除 myns: 前缀。

    来自annotationsTable 模板中的myns:annotation

    <xsl:template name="annotationsTable">
        ...
            <fo:table-body>
                <xsl:apply-templates select="annotation" />
            </fo:table-body>
        </fo:table>
    </xsl:template>
    

    来自myns:annotation模板中的myns:annotationmyns:text元素:

    <xsl:template match="annotation">
        <fo:table-row>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="text" />
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="@createdByName"/>
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="@createdByUserID" />
                </fo:block>
            </fo:table-cell>
            <fo:table-cell>
                <fo:block>
                    <xsl:value-of select="@systemDate" />
                </fo:block>
            </fo:table-cell>
        </fo:table-row>
    </xsl:template>
    

    现在它应该生成表格正文内容了。

    2) 如果一开始就有命名空间前缀,那可能是您的源最初有一个命名空间。在这种情况下,您按原样保留您的 XSLT,并编辑您的源代码,声明一个默认命名空间:

    <annotation xmlns="http://xmlapp.fm.net/ns/app/service" 
                createdByName="Frank" createdByUserID="X1234" systemDate="2014-04-14">
        <text>this is the text of an annotation</text>
    </annotation>
    

    现在所有元素都属于“http://xmlapp.fm.net/ns/app/service”命名空间,并且您的 XSLT 将该命名空间映射到前缀 (myns),因此您可以在 XPath 中选择源树的节点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-13
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      • 2018-06-22
      • 2021-01-16
      • 1970-01-01
      相关资源
      最近更新 更多