XSLT:处理内部XML

本文关键字:XML 内部 处理 XSLT | 更新日期: 2023-09-27 18:07:19

我正在尝试处理XML内部文本。我有以下XSLT片段:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="refsect1[@id='errors']/param">
        <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="param/constant">
        <i><xsl:apply-templates/></i>
    </xsl:template>
    <xsl:template match="param/parameter">
        <paramref cref="{.}"/>
    </xsl:template>
    <xsl:variable name="lowercase" select="'abcdefghijklmnopqrstuvwxyz'"/>
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
    <xsl:template name="summary" match="refentry">
/// <summary>
/// <xsl:value-of select="concat(translate(
                    substring(refnamediv/refpurpose, 1, 1), $lowercase, $uppercase),
                    substring(refnamediv/refpurpose, 2, string-length(refnamediv/refpurpose) - 1))"/>
/// </summary>
        <xsl:for-each select="refsect1/variablelist/varlistentry">
            <xsl:choose>
                <xsl:when test="../../@id = 'parameters'">
/// <param name="{term/parameter}">
        <xsl:for-each select="listitem/para">
/// <xsl:value-of select="normalize-space(.)"/>
        </xsl:for-each>
/// </param>
                </xsl:when>
            </xsl:choose>
        </xsl:for-each>
/// <remarks>
/// <para>
/// This routine generates the following errors (detectable with <see cref="Gl.GetError"/>):
        <xsl:for-each select="refsect1[@id='errors']/para">
/// <xsl:value-of select="normalize-space(.)"/>
        </xsl:for-each>
/// </para>
/// </remarks>
        <xsl:for-each select="refsect1[@id = 'seealso']/para/citerefentry">
/// <seealso cref="Gl.{substring(refentrytitle, 3)}"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

此XSLT应应用于XML文档;下面是一个代码片段:

<refsect1 id="errors"><title>Errors</title>
    <para>
        <constant>GL_INVALID_OPERATION</constant> is generated if <parameter>pipeline</parameter> is not
        a name previously returned from a call to <citerefentry><refentrytitle>glGenProgramPipelines</refentrytitle></citerefentry>
        or if such a name has been deleted by a call to
        <citerefentry><refentrytitle>glDeleteProgramPipelines</refentrytitle></citerefentry>.
    </para>
    <para>
        <constant>GL_INVALID_OPERATION</constant> is generated if <parameter>program</parameter> refers
        to a program object that has not been successfully linked.
    </para>
</refsect1>

我当前的输出实际上是一个纯文本:

/// <remarks>
/// <para>
/// This routine generates the following errors (detectable with <see cref="Gl.GetError" />):
/// GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call to glGenProgramPipelines or if such a name has been deleted by a call to glDeleteProgramPipelines.
/// GL_INVALID_OPERATION is generated if program refers to a program object that has not been successfully linked.
/// </para>
/// </remarks>

但是我想处理它,以便在其他标签中转换内部标签。例如:

& lt; costant>text 应当成为 & lt; i> text

*GL_PARAM*变成


如何达到这个结果?


在Alexander帮助我之后,我得到了我必须调用xsl:apply-template。它开始工作,但我无法控制空格规范化:

/// <para>
/// This routine generates the following errors (detectable with <see cref="Gl.GetError" />):
    <i>GL_INVALID_OPERATION</i> is generated if <paramref cref="pipeline" /> is not
        a name previously returned from a call to glGenProgramPipelines
        or if such a name has been deleted by a call to
        glDeleteProgramPipelines.
    <i>GL_INVALID_OPERATION</i> is generated if <paramref cref="program" /> refers
        to a program object that has not been successfully linked.
/// </para>

我在foreach指令之后调用xsl:apply-template:

/// <para>
/// This routine generates the following errors (detectable with <see cref="Gl.GetError"/>):
    <xsl:for-each select="refsect1[@id='errors']/para">
        <xsl:apply-templates/>
    </xsl:for-each>
/// </para>

XSLT:处理内部XML

技巧之一是理解函数式和声明式编程的强大功能。你现在有一个非常命令式的风格,所以让我们重写一下;

<xsl:template match="refsect1[@id='errors']/param">
   <xsl:apply-templates />
</xsl:template>
<xsl:template match="param/constant">
   <i><xsl:apply-templates /></i>
</xsl:template>
<xsl:template match="param/parameter">
   <paramref cref="{.}" />
</xsl:template>

这就是你所需要的。基本上,不要遍历XML的所有部分并尝试在那一点上做一些事情,而是使用模板系统来匹配有问题的项,并使其更有效和强大。

最后,如果GL_PARAM到Gl.PARAM不是拼写错误,则需要在顶部进行一些额外的文本转换,但如果您知道公式(您没有说:),那么这并不难,可以使用before-substring()、after-substring()和translate()。