我正在编写一些xsl,以将xml中的书籍大纲转换为一堆单独的xml文件(每个章节一个,外加一些前置内容,等等)。我将使用<exsl:document>
进行此操作,各个文件的大部分内容都将写入xsl内。
我使用xsltproc,所以使用xslt 1.0。
我想要文本注释,我可以使用<xsl:comment>
获得注释,但也需要一些“注释掉”的xml。如this question中所述,无法使用<xsl:comment>
。
该问题的answer使用<xsl:text disable-output-escaping="yes"><!--</xsl:text>
来包装注释的xml。这是可行的,除了添加后,输出不再正确缩进即可。
例如,以下xsl:
<?xml version='1.0' encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<root>
<xsl:comment>Text comment</xsl:comment>
<child><name>A child</name></child>
<xsl:text disable-output-escaping="yes"><!--</xsl:text>
<child><name>commented child</name></child>
<xsl:text disable-output-escaping="yes">--></xsl:text>
</root>
</xsl:template>
</xsl:stylesheet>
提供注释中的xml,但没有缩进:
<root><!--Text comment--><child><name>A child</name></child><!--<child><name>commented child</name></child>--></root>
在使用时:
<xsl:template match="/">
<root>
<xsl:comment>Text comment</xsl:comment>
<child><name>A child</name></child>
<xsl:comment><child><name>commented child</name></child></xsl:comment>
</root>
</xsl:template>
缩进很好,但注释中没有xml标记:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<!--Text comment-->
<child>
<name>A child</name>
</child>
<!--commented child-->
</root>
有什么办法可以缩进,但可以将xml代码放在注释中吗?
答案 0 :(得分:0)
这是可用于注释掉任何XML节点或片段的转换,:
============================
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:value-of select="'<!--
'"/>
<xsl:apply-templates select="*" mode="escapeToText"/>
<xsl:value-of select="'
-->'"/>
</xsl:template>
<xsl:template match="*" mode="escapeToText">
<xsl:value-of select="concat('<', name())"/>
<xsl:apply-templates select="@*" mode="escapeToText"/>
<xsl:value-of select="'>'"/>
<xsl:apply-templates select="node()" mode="escapeToText"/>
<xsl:value-of select="concat('</', name(), '>')"/>
</xsl:template>
<xsl:template match="@*" mode="escapeToText">
<xsl:value-of select="concat(' ', name(), '="')"/>
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="string(.)"/>
</xsl:call-template>
<xsl:value-of select="'"'"/>
</xsl:template>
<xsl:template match="text()" mode="escapeToText">
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template match="processing-instruction()" mode="escapeToText">
<xsl:value-of select="concat('<?', name(), ' ', ., ' ?>')"/>
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="concat('<!CM ', ., 'CM>')"/>
</xsl:template>
<xsl:template name="escapeDoubleDash">
<xsl:param name="pText"/>
<xsl:choose>
<xsl:when test="contains($pText, '--')">
<xsl:value-of select="substring-before($pText, '--')"/>
<xsl:value-of select="'!-!-'"/>
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="substring-after($pText, '--')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$pText"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
当此转换应用于任何源xml文档时,例如:
<input>
<name>Jack</name>
<age>23</age>
<type-10-num>1</type-10-num>
<type-20-num>2</type-20-num>
<type-20-char>3</type-20-char>
<type-180-num>4</type-180-num>
<type-180-char>5</type-180-char>
<type-180-str>6</type-180-str>
</input>
产生所需的缩进结果:
<!--
<input>
<name>Jack</name>
<age>23</age>
<type-10-num>1</type-10-num>
<type-20-num>2</type-20-num>
<type-20-char>3</type-20-char>
<type-180-num>4</type-180-num>
<type-180-char>5</type-180-char>
<type-180-str>6</type-180-str>
</input>
-->
以下是注释掉的非常复杂的XML文档的样子-让我们将此转换应用于...本身。
为完整起见,我在模板匹配属性之前添加了注释和处理说明:
<?somePI x="y" z="t" pqr ?>
<!-- A Comment node -->
结果如预期:
<!--
<xsl:stylesheet version="1.0">
<xsl:output method="text" indent="yes"></xsl:output>
<xsl:template match="/">
<xsl:value-of select="'<!!-!-
'"></xsl:value-of>
<xsl:apply-templates select="*" mode="escapeToText"></xsl:apply-templates>
<xsl:value-of select="'
!-!->'"></xsl:value-of>
</xsl:template>
<xsl:template match="*" mode="escapeToText">
<xsl:value-of select="concat('<', name())"></xsl:value-of>
<xsl:apply-templates select="@*" mode="escapeToText"></xsl:apply-templates>
<xsl:value-of select="'>'"></xsl:value-of>
<xsl:apply-templates select="node()" mode="escapeToText"></xsl:apply-templates>
<xsl:value-of select="concat('</', name(), '>')"></xsl:value-of>
</xsl:template>
<?somePI x="y" z="t" pqr ?>
<!CM A Comment node CM>
<xsl:template match="@*" mode="escapeToText">
<xsl:value-of select="concat(' ', name(), '="')"></xsl:value-of>
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="string(.)"></xsl:with-param>
</xsl:call-template>
<xsl:value-of select="'"'"></xsl:value-of>
</xsl:template>
<xsl:template match="text()" mode="escapeToText">
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="."></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="processing-instruction()" mode="escapeToText">
<xsl:value-of select="concat('<?', name(), ' ', ., ' ?>')"></xsl:value-of>
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="concat('<!CM ', ., 'CM>')"></xsl:value-of>
</xsl:template>
<xsl:template name="escapeDoubleDash">
<xsl:param name="pText"></xsl:param>
<xsl:choose>
<xsl:when test="contains($pText, '!-!-')">
<xsl:value-of select="substring-before($pText, '!-!-')"></xsl:value-of>
<xsl:value-of select="'!-!-'"></xsl:value-of>
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="substring-after($pText, '!-!-')"></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$pText"></xsl:value-of></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
-->
更新:
如果您希望注释的结果作为XML文档的一部分出现-也就是说,不要包含<xsl:output method="text"/>
,
我建议添加一个特殊元素,例如<MyComment>
并将注释的结果作为<MyComment>
的文本节点子代生成。通常,带有注释的xml片段会以特殊字符转义。
但是有一个窍门-使用CDATA部分-然后您将看到文本未转义。最好在一个示例中看到:
更新后的转换与上面提供的转换几乎相同,但是:
method="text"
指令中没有<xsl:output>
<MyComment>
元素的文本节点这是修改后的转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" cdata-section-elements="MyComment"/>
<xsl:template match="/">
<MyComment>
<xsl:value-of select="'<!--
'"/>
<xsl:apply-templates select="*" mode="escapeToText"/>
<xsl:value-of select="'
-->'"/>
</MyComment>
</xsl:template>
<xsl:template match="*" mode="escapeToText">
<xsl:value-of select="concat('<', name())"/>
<xsl:apply-templates select="@*" mode="escapeToText"/>
<xsl:value-of select="'>'"/>
<xsl:apply-templates select="node()" mode="escapeToText"/>
<xsl:value-of select="concat('</', name(), '>')"/>
</xsl:template>
<xsl:template match="@*" mode="escapeToText">
<xsl:value-of select="concat(' ', name(), '="')"/>
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="string(.)"/>
</xsl:call-template>
<xsl:value-of select="'"'"/>
</xsl:template>
<xsl:template match="text()" mode="escapeToText">
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template match="processing-instruction()" mode="escapeToText">
<xsl:value-of select="concat('<?', name(), ' ', ., ' ?>')"/>
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="concat('<!CM ', ., 'CM>')"/>
</xsl:template>
<xsl:template name="escapeDoubleDash">
<xsl:param name="pText"/>
<xsl:choose>
<xsl:when test="contains($pText, '--')">
<xsl:value-of select="substring-before($pText, '--')"/>
<xsl:value-of select="'!-!-'"/>
<xsl:call-template name="escapeDoubleDash">
<xsl:with-param name="pText" select="substring-after($pText, '--')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$pText"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
当我们将此转换应用于以下XML文档时:
<input>
<name>Jack</name>
<age>23</age>
<type-10-num>1</type-10-num>
<type-20-num>2</type-20-num>
<type-20-char>3</type-20-char>
<type-180-num>4</type-180-num>
<type-180-char>5</type-180-char>
<type-180-str>6</type-180-str>
</input>
产生了想要的,未经转义的评论:
<MyComment><![CDATA[<!--
<input>
<name>Jack</name>
<age>23</age>
<type-10-num>1</type-10-num>
<type-20-num>2</type-20-num>
<type-20-char>3</type-20-char>
<type-180-num>4</type-180-num>
<type-180-char>5</type-180-char>
<type-180-str>6</type-180-str>
</input>
-->]]></MyComment>
我们可以摆脱XML注释(<!-- -->
)和处理“嵌套注释”的代码-不再需要。