【问题标题】:Inserting ENTITY declarations in DOCTYPE XSLT 2.0 Saxon9he在 DOCTYPE XSLT 2.0 Saxon9he 中插入 ENTITY 声明
【发布时间】:2020-07-20 04:12:34
【问题描述】:

我的任务是将 XML 文档分解为单独的工作包。我唯一遇到问题的部分是在 DOCTYPE 中插入图形实体声明,如下所示:

<!DOCTYPE frntcover PUBLIC "-//USA-DOD//DTD TM Assembly REV C" "production.dtd" [
<!ENTITY IMAGE001.jpg SYSTEM "IMAGE001.jpg" NDATA jpg>
]>

(不要介意实体名称中的扩展名,这就是他们在这里的做法。)无论如何,实体将由在主 XML 文件中找到的所有 @boardno 构成,这些文件可能位于 &lt;figure&gt; 中或&lt;graphic&gt;&lt;graphic boardno="IMAGE001.jpg"/&gt;

我一直在使用&lt;xsl:result-document&gt; 写出文档类型,但我不知道如何在其中获取实体。

我尝试了 LexEv,但收到了net.sf.saxon.trans.XPathException: Failed to instantiate class com.andrewjwelch.lexev.LexEv (does it have a public zero-argument constructor?) 我联系了 Andrew,他说 LexEv 不再受支持,而且不是我需要的工具,因为 LexEv 用于保存实体,而不是用于将它们写入文件。

【问题讨论】:

    标签: xml entity xslt-2.0 doctype


    【解决方案1】:

    就像 Kay 博士建议的那样,您可以使用 DOE(禁用输出转义)手动创建它。

    这与我过去使用的类似。我通常做的是使用 Python 创建实体声明,然后将它们作为参数传递给样式表。

    我使用 xsl:key,所以我不会得到重复的声明。

    此外,您还可以重构符号数据的确定方式;特别是如果符号始终与文件扩展名相同。

    示例...

    XML 输入

    <frntcover>
        <graphic boardno="IMAGE001.jpg"/>
        <figure boardno="IMAGE001.jpg"/>
        <graphic boardno="IMAGE002.jpg"/>
        <graphic boardno="IMAGE003.jpg"/>
    </frntcover>
    

    XSLT 2.0

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key name="_gd_gnbrs" match="*[@boardno]" use="@boardno"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="/*">
        <xsl:call-template name="generate_doctype">
          <xsl:with-param name="root" select="local-name()"/>
          <xsl:with-param name="pubid" select="'-//USA-DOD//DTD TM Assembly REV C'"/>
          <xsl:with-param name="sysid" select="'production.dtd'"/>
        </xsl:call-template>
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template name="generate_doctype">
        <xsl:param name="root"/>
        <xsl:param name="pubid"/>
        <xsl:param name="sysid"/>
        <xsl:text disable-output-escaping="yes">&#xA;<![CDATA[<!DOCTYPE ]]></xsl:text>
        <xsl:value-of select="$root"/>
        <xsl:choose>
          <xsl:when test="string($pubid)">
            <xsl:value-of select="concat(' PUBLIC &quot;',$pubid,'&quot;')" disable-output-escaping="yes"/>
          </xsl:when>
          <xsl:when test="string($sysid)">
            <xsl:text> SYSTEM</xsl:text>
          </xsl:when>
        </xsl:choose>
        <xsl:if test="string($sysid)">
          <xsl:value-of select="concat(' &quot;',$sysid,'&quot;')" disable-output-escaping="yes"/>
        </xsl:if>
        <xsl:text disable-output-escaping="yes"><![CDATA[ []]>&#xA;</xsl:text>
        <xsl:for-each select="//*[@boardno][count(.|key('_gd_gnbrs',@boardno)[1])=1]">
          <xsl:apply-templates select="." mode="ent_decs"/>
        </xsl:for-each>
        <xsl:text disable-output-escaping="yes"><![CDATA[]>]]>&#xA;</xsl:text>
      </xsl:template>
    
      <xsl:template match="*" mode="ent_decs">
        <xsl:text disable-output-escaping="yes"><![CDATA[<!ENTITY ]]></xsl:text>
        <xsl:value-of select="concat(@boardno,' SYSTEM &quot;',@boardno)" disable-output-escaping="yes"/>
        <xsl:choose>
          <xsl:when test="matches(@boardno,'\.tif','i')">
            <xsl:text disable-output-escaping="yes"><![CDATA[" NDATA ccitt4>]]>&#xA;</xsl:text>        
          </xsl:when>
          <xsl:when test="matches(@boardno,'\.cgm','i')">
            <xsl:text disable-output-escaping="yes"><![CDATA[" NDATA cgm>]]>&#xA;</xsl:text>
          </xsl:when>
          <xsl:when test="matches(@boardno,'\.jpe?g','i')">
            <xsl:text disable-output-escaping="yes"><![CDATA[" NDATA jpg>]]>&#xA;</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:message terminate="yes">UNKNOWN GRAPHIC EXTENSION: "<xsl:value-of select="@boardno"/>"</xsl:message>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    
    </xsl:stylesheet>
    

    XML 输出

    <!DOCTYPE frntcover PUBLIC "-//USA-DOD//DTD TM Assembly REV C" "production.dtd" [
    <!ENTITY IMAGE001.jpg SYSTEM "IMAGE001.jpg" NDATA jpg>
    <!ENTITY IMAGE002.jpg SYSTEM "IMAGE002.jpg" NDATA jpg>
    <!ENTITY IMAGE003.jpg SYSTEM "IMAGE003.jpg" NDATA jpg>
    ]>
    <frntcover>
       <graphic boardno="IMAGE001.jpg"/>
       <figure boardno="IMAGE001.jpg"/>
       <graphic boardno="IMAGE002.jpg"/>
       <graphic boardno="IMAGE003.jpg"/>
    </frntcover>
    

    小提琴:http://xsltfiddle.liberty-development.net/gVhDDyQ

    【讨论】:

    • 谢谢丹尼尔,帮了大忙。
    【解决方案2】:

    Saxon 确实有一个扩展名 saxon:doctype 用于将 DTD 添加到输出文档:请参阅 http://www.saxonica.com/documentation/index.html#!extensions/instructions/doctype

    但它需要 Saxon-PE 或更高版本。

    唯一的其他选择是“手动”构建它并使用禁用输出转义输出它。或者使用 Perl 或 awk 等“纯文本”转换工具进行一些后期处理。

    【讨论】:

    • 谢谢,我会让老板知道我们应该考虑升级。
    猜你喜欢
    • 2012-03-21
    • 1970-01-01
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 2015-07-03
    • 1970-01-01
    • 2017-08-31
    • 2012-11-27
    相关资源
    最近更新 更多