【问题标题】:XSL: Include some ASCII control chars when method="text"XSL:在 method="text" 时包含一些 ASCII 控制字符
【发布时间】:2010-02-11 10:33:34
【问题描述】:

我有一个输出文本而不是 XML 的 XSL 模板。 在本文中,我需要在特定位置包含 ASCII 字符 0x10。

我知道这个字符在 XML 文档中是不允许的,但我要输出文本,为什么我还是不允许使用它?

我也明白,无论是在CDATA 部分中还是 中,都无法将这个字符逐字放入模板中。但是为什么即时生成也不起作用?例如,我尝试定义一个返回此字符并将其用作<xsl:value-of select="z:get_char(16)"/> 的函数,但这也会产生一个无效字符异常。

有办法吗?

【问题讨论】:

    标签: xslt escaping ascii xml-1.1


    【解决方案1】:

    Microsoft .NET 框架不支持 XML 1.1,这是真的,但它有自己的(不可移植的)方式来使用 XML 1.0 文档中的控制字符,即如果您设置 CheckCharacters,您可以将其作为数字字符引用在您的 XmlReaderSettings/XmlWriterSettings 上设置为 false。

    这是一个示例样式表和一些使用 .NET 3.5 测试的不会引发非法字符异常的 .NET 代码:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet
      version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:output method="text"/>
    
      <xsl:template match="/">
        <xsl:text>&#x10;</xsl:text>
      </xsl:template>
    </xsl:stylesheet>
    

     

    XmlReaderSettings xrs = new XmlReaderSettings();
    xrs.CheckCharacters = false;
    
    XslCompiledTransform proc = new XslCompiledTransform();
    using (XmlReader xr = XmlReader.Create(@"sheet.xslt", xrs))
    {
        proc.Load(xr);
    }
    
    using (XmlReader xr = XmlReader.Create(new StringReader("<foo/>")))
    {
        XmlWriterSettings xws = proc.OutputSettings.Clone();
        xws.CheckCharacters = false;
    
        using (XmlWriter xw = XmlWriter.Create(@"result.txt", xws))
        {
            proc.Transform(xr, null, xw);
            xw.Close();
        }
        xr.Close();
    }
    

    【讨论】:

    • 优秀。我必须做的唯一更改是将disable-output-escaping="yes" 添加到xsl:text,否则该字符将作为实体&amp;#x10; 出现在输出中,我希望它作为一个字符。
    • 甚至可以不禁用输出转义,只要您使用 xsl:output method="text" 并在 .NET 代码中稍作更改。我将编辑我的答案以显示该更改。
    • 太棒了!不能再投票了。但是,是否需要在这些上使用usingusing相当于在finally中调用Dispose,不能直接调用,因为是protected;因此,using 无效,您只需调用 Close?
    • 我认为 'using' 语句是实现 IDisposable 对象的正确方法,但对于这个线程的主题来说肯定不是关键的,即能够在 XML 1.0 中使用控制字符的字符引用使用 .NET 框架的 XslCompiledTransform 输出带有控制字符的文本文件的样式表。
    【解决方案2】:

    由于 XSLT 文件是 XML 文件,因此您不能包含该字符引用。我认为您无法在纯 XSLT 解决方案中做到这一点。

    ASCII 字符 HEX 10/DEC 16 是 Data Link Escape (DLE) control character

    XML Spec 只允许三个空格(制表符、回车、换行)控制字符

    合法字符是制表符、回车 返回、换行和合法的 Unicode 和 ISO/IEC 字符 10646.

    0x20 以下的所有内容都是不允许的。

    字符范围 2 字符 ::=
    #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* 任何 Unicode 字符,不包括代理 块、FFFE 和 FFFF。 */

    一种选择是在您的输出中为该字符放置一个占位符标记值,然后使用外部进程来查找/替换该字符的标记。

    【讨论】:

      【解决方案3】:

      如果您可以使用 XML 1.1(它允许在 XML 文档中插入此类字符作为字符引用),那么以下应该可以工作,至少它适用于 Sun Java 6 和 Saxon 9.2:

      <?xml version="1.1" encoding="UTF-8"?>
      <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0">
      
        <xsl:output method="text"/>
      
        <xsl:template name="main">
          <xsl:text>&#x10;</xsl:text>
        </xsl:template>
      
      </xsl:stylesheet>
      

      【讨论】:

      • 唉,我在 .NET 中使用 XSLCompiledTransform。那里不支持 1.1 版。但是+1。
      【解决方案4】:

      过去,我曾使用这种技术在 XHTML 生成的文本区域中输入换行符。如果我没有输入至少一个字符,textarea 会自动关闭(导致浏览器问题)。请注意,该字符包含在 &lt;xsl:text&gt; 中。此外,原始源代码在一行中,但为了便于阅读,我进行了格式化。

      <textarea name="qry" rows="4" cols="50" id="query">
       <xsl:value-of select="$qry" /><xsl:text>&#x0A;</xsl:text>
      </textarea>
      

      【讨论】:

      • 好吧,但是换行符是合法字符之一,这会使您的代码处于不同的情况......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      • 1970-01-01
      • 2018-11-27
      • 2016-01-29
      • 2016-05-21
      相关资源
      最近更新 更多