代码之家  ›  专栏  ›  技术社区  ›  codymanix

XSLT转换创建StackoverflowException

  •  1
  • codymanix  · 技术社区  · 16 年前

    void Convert()
    {
                XPathDocument xpathDoc = new XPathDocument(@"myschema.xsd");
                string xslPath = @"convert.xsl";
                XslCompiledTransform transform = new XslCompiledTransform();               
                transform.Load(xslPath, new XsltSettings(true, true), null);    
                using (FileStream fs = File.Create(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "output.sql")))
                {
                    try
                    {
                        transform.Transform(xpathDoc, null, fs);
                    }
                    catch
                    {
                        fs.Close();
                    }
                }
    }
    

    这是失败的XSLT文件:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                   version="1.0" 
                   xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
    <!-- Get schema nodes from this schema and any included schemas -->
    <xsl:variable name="contents" select="/|document(//xs:include/@schemaLocation)" />
    
    <xsl:template match="*" >
    
     <xsl:for-each select="$contents" >
      <xsl:apply-templates select=".//xs:element" />
     </xsl:for-each>
    
    </xsl:template>
    
    <xsl:template match="xs:element">
    
        <xsl:apply-templates />
    
    </xsl:template>
    
    </xsl:stylesheet>
    

    编辑: 原始代码来自 here 它已经有错误了。我试图通过简化XSLT来修复它,直到只剩下错误为止。

    3 回复  |  直到 16 年前
        1
  •  4
  •   Woody    16 年前

    线路

    <xsl:apply-templates select=".//xs:element" />
    

        2
  •  0
  •   Dimitre Novatchev    16 年前

    导致无休止递归的问题如下:

    <xsl:template match="xs:element">  
    
        <xsl:apply-templates />  
    
    </xsl:template>
    

    这个 <xsl:apply-templates> 指令将导致处理xs:element以外的其他元素。对于所有这些元素,选择以下模板进行处理:

    <xsl:template match="*" >     
    
     <xsl:for-each select="$contents" >     
      <xsl:apply-templates select=".//xs:element" />     
     </xsl:for-each>     
    
    </xsl:template>  
    

    这个问题是可以避免的 按以下方式:

      <xsl:template match="xs:include">
       <xsl:apply-templates select="document(@schemaLocation)/*/>
      </xsl:template>
    

    没有其他 特殊的 模板是必要的——只需添加处理特定xsd元素的模板。

        3
  •  0
  •   user357812 user357812    16 年前

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xsl:template match="/" name="root">
            <xsl:param name="schema" select="*/*"/>
            <xsl:choose>
                <xsl:when test="$schema[self::xs:include]">
                    <xsl:call-template name="root">
                        <xsl:with-param name="schema" select="$schema[not(self::xs:include)]|document($schema[self::xs:include]/@schemaLocation)/*/*"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="*/*">
                        <xsl:with-param name="schema" select="$schema"/>
                    </xsl:apply-templates>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>
    

    使用此样式表,您需要使用param添加模板 schema 是你的扩展模式。此外,还需要使用参数应用模板 架构 select="$schema" .

    编辑 :抱歉,有点小错误。另外,还有一个解释:当处理模块化模式时,需要首先获得完整的扩展模式,否则每次都会调用递归模板来获取不同模式模块中的引用和类型定义。使用我的模板,您可以在 $schema param,所以当你处理一个 xs:element 具有 @type="someType" 你可以继续这个过程 xsl:apply-templates select="$schema[self::xs:complexType[@name='someType']]" .