在 DOCTYPE XSLT 2.0 Saxon9he 中插入 ENTITY 声明
Inserting ENTITY declarations in DOCTYPE XSLT 2.0 Saxon9he
我的任务是将 XML 文档分解成单独的工作包。我遇到的唯一问题是在 DOCTYPE 中插入图形实体声明,如下所示:
<!DOCTYPE frntcover PUBLIC "-//USA-DOD//DTD TM Assembly REV C" "production.dtd" [
<!ENTITY IMAGE001.jpg SYSTEM "IMAGE001.jpg" NDATA jpg>
]>
(不要在意实体名称中的扩展名,他们在这里就是这样做的。)无论如何,实体将由主 XML 文件中的所有 @boardno
构建可以在 <figure>
或 <graphic>
中,即 <graphic boardno="IMAGE001.jpg"/>
我一直在使用 <xsl:result-document>
写出文档类型,但我不知道如何在其中获取实体。
我尝试了 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 用于保存实体而不是将它们写入文件。
Saxon 确实有一个扩展 saxon:doctype
用于将 DTD 添加到输出文档:请参阅 http://www.saxonica.com/documentation/index.html#!extensions/instructions/doctype
但它需要 Saxon-PE 或更高版本。
唯一的其他选择是构造它 "by hand" 并使用 disable-output-escaping 输出它。或者使用 Perl 或 awk 等 "plain text" 转换工具进行一些 post 处理。
正如 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">
<![CDATA[<!DOCTYPE ]]></xsl:text>
<xsl:value-of select="$root"/>
<xsl:choose>
<xsl:when test="string($pubid)">
<xsl:value-of select="concat(' PUBLIC "',$pubid,'"')" 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(' "',$sysid,'"')" disable-output-escaping="yes"/>
</xsl:if>
<xsl:text disable-output-escaping="yes"><![CDATA[ []]>
</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[]>]]>
</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 "',@boardno)" disable-output-escaping="yes"/>
<xsl:choose>
<xsl:when test="matches(@boardno,'\.tif','i')">
<xsl:text disable-output-escaping="yes"><![CDATA[" NDATA ccitt4>]]>
</xsl:text>
</xsl:when>
<xsl:when test="matches(@boardno,'\.cgm','i')">
<xsl:text disable-output-escaping="yes"><![CDATA[" NDATA cgm>]]>
</xsl:text>
</xsl:when>
<xsl:when test="matches(@boardno,'\.jpe?g','i')">
<xsl:text disable-output-escaping="yes"><![CDATA[" NDATA jpg>]]>
</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>
我的任务是将 XML 文档分解成单独的工作包。我遇到的唯一问题是在 DOCTYPE 中插入图形实体声明,如下所示:
<!DOCTYPE frntcover PUBLIC "-//USA-DOD//DTD TM Assembly REV C" "production.dtd" [
<!ENTITY IMAGE001.jpg SYSTEM "IMAGE001.jpg" NDATA jpg>
]>
(不要在意实体名称中的扩展名,他们在这里就是这样做的。)无论如何,实体将由主 XML 文件中的所有 @boardno
构建可以在 <figure>
或 <graphic>
中,即 <graphic boardno="IMAGE001.jpg"/>
我一直在使用 <xsl:result-document>
写出文档类型,但我不知道如何在其中获取实体。
我尝试了 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 用于保存实体而不是将它们写入文件。
Saxon 确实有一个扩展 saxon:doctype
用于将 DTD 添加到输出文档:请参阅 http://www.saxonica.com/documentation/index.html#!extensions/instructions/doctype
但它需要 Saxon-PE 或更高版本。
唯一的其他选择是构造它 "by hand" 并使用 disable-output-escaping 输出它。或者使用 Perl 或 awk 等 "plain text" 转换工具进行一些 post 处理。
正如 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">
<![CDATA[<!DOCTYPE ]]></xsl:text>
<xsl:value-of select="$root"/>
<xsl:choose>
<xsl:when test="string($pubid)">
<xsl:value-of select="concat(' PUBLIC "',$pubid,'"')" 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(' "',$sysid,'"')" disable-output-escaping="yes"/>
</xsl:if>
<xsl:text disable-output-escaping="yes"><![CDATA[ []]>
</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[]>]]>
</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 "',@boardno)" disable-output-escaping="yes"/>
<xsl:choose>
<xsl:when test="matches(@boardno,'\.tif','i')">
<xsl:text disable-output-escaping="yes"><![CDATA[" NDATA ccitt4>]]>
</xsl:text>
</xsl:when>
<xsl:when test="matches(@boardno,'\.cgm','i')">
<xsl:text disable-output-escaping="yes"><![CDATA[" NDATA cgm>]]>
</xsl:text>
</xsl:when>
<xsl:when test="matches(@boardno,'\.jpe?g','i')">
<xsl:text disable-output-escaping="yes"><![CDATA[" NDATA jpg>]]>
</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>