XSL 排序问题

2023-12-19

我在尝试使用 CLR4.0 中的 XslCompiledTransform 对 XSL 文件进行排序时遇到问题。这是我的示例 XML 文件(注意:第二个后面有一个空格<foo>元素):

<?xml version="1.0" encoding="utf-8"?>
<reflection> 
  <apis>
    <api id="A">
      <foos>
        <foo/>
      </foos>
    </api>
    <api id="B">
      <foos>
        <foo/> 
      </foos>
    </api>     
  </apis>
</reflection>

当我应用以下 XSL 文件时:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">
  <xsl:template match="/">
    <html>
      <body>
        <table>
          <xsl:apply-templates select="/reflection/apis/api">
                        <xsl:sort select="@id" />
                    </xsl:apply-templates>          
        </table>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="api">
    <tr>
      <td>
        <xsl:value-of select="@id" />
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>

我得到以下结果:

<html>
  <body>
    <table>
      <tr>
        <td>B</td>
      </tr>
      <tr>
        <td>A</td>
      </tr>
    </table>
  </body>
</html>

但是,如果我删除第二个之后的空格<foo>元素,结果文件排序正确。这看起来可能是 XslCompiledTransform 中的一个错误,但我希望有人可能有解决方法。

编辑:如果有人在复制时遇到问题,这是我正在使用的代码:

XslCompiledTransform xslt = new XslCompiledTransform();
XsltSettings transformSettings = new XsltSettings(true, true);
xslt.Load("CreateVSToc.xsl", transformSettings, new XmlUrlResolver());

XmlReaderSettings readerSettings = new XmlReaderSettings();
readerSettings.IgnoreWhitespace = true;
Stream readStream = File.Open("reflection.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
using (XmlReader reader = XmlReader.Create(readStream, readerSettings))
{
    Stream outputStream = File.Open("toc.xml", FileMode.Create, FileAccess.Write, FileShare.Read | FileShare.Delete);
    using (XmlWriter writer = XmlWriter.Create(outputStream, xslt.OutputSettings))
    {

        XsltArgumentList arguments = new XsltArgumentList();
        xslt.Transform(reader, arguments, writer);
    }
}

可疑的是,如果每个的 XMLapi元素修改为以下内容,结果将按预期排序:

<api id="apiId">
   <id>apiId</id>
   <foos>
      <foo />
   </foo>       
</api>

此外,如果 a) 每个的 XMLapi元素被修改以删除id完全属性

<api>
   <id>apiId</id>
   <foos>
      <foo />
   </foo>       
</api>

b) 仅second参考@idXSL 文件中的内容更改为id,结果仍将按字母顺序排序!


有可能的是XslCompiledTransform正在尝试对名为的子元素进行排序id而不是名为的属性id,或者这可能只是运气不好。不管怎样,我已经验证它愿意对名为的子元素进行正确排序id.

考虑到这一点,我可以想到两种解决方法,但这两种方法都要求您对转换过程有一定程度的控制。

方法 1:您可以更改 XML

更改写入原始 XML 的过程以指定id作为包含的第一个元素api元素。然后更新 XSL 以替换对的引用@id with id.

方法 2:您可以在应用 XSL 之前预处理 XML

使用 XSL 转换来移动id属性到子元素中api,然后应用与您在中相同的 XSL方法一到中间 XML 文档。在处理大型 XML 文件时,将文档转换两次显然不太理想。

以下 XSL 将使您从原始 XML 转换为中间 XML:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1">  
   <!-- recursively copy each element (including root) -->
   <xsl:template match="*|/">
      <xsl:copy>      
         <!-- xsl:copy ignores attributes, copy those as well -->
         <xsl:copy-of select="@*"/>      
         <!-- continue to deep copy the element -->
         <xsl:apply-templates />      
      </xsl:copy>
   </xsl:template>    
   <!-- for api elements, move the id attribute into an element -->
   <xsl:template match="api">
      <api>
         <id>
            <xsl:value-of select="@id"/>
         </id>      
         <!-- continue deep copy of api element contents -->
         <xsl:apply-templates />
      </api>
   </xsl:template>   
</xsl:stylesheet>

我希望这有帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

XSL 排序问题 的相关文章

随机推荐