Internet explorer 模板递归错误

Internet explorer 模板递归错误,internet-explorer,firefox,xslt,recursion,Internet Explorer,Firefox,Xslt,Recursion,我正在更新我的XST知识,并决定尝试制作一个XSLT1.0样式表,将C#编译器中的XMLHelp文件转换为更好的格式 有许多问题需要解决,但目前我只是尝试解析那些恼人的成员名称属性,并创建另一个XML文档,其中提取“:”和“.”字符之间的标记并将其转换为元素 首先,我想转向如下内容: <member name="T:PrimeNumbers.Properties.Resources"> <member type="T"> <Properties>

我正在更新我的XST知识,并决定尝试制作一个XSLT1.0样式表,将C#编译器中的XMLHelp文件转换为更好的格式

有许多问题需要解决,但目前我只是尝试解析那些恼人的成员名称属性,并创建另一个XML文档,其中提取“:”和“.”字符之间的标记并将其转换为元素

首先,我想转向如下内容:

<member name="T:PrimeNumbers.Properties.Resources">
<member type="T">
  <Properties>
    <Resources />
  </Properties>
</member>

变成类似于:

<member name="T:PrimeNumbers.Properties.Resources">
<member type="T">
  <Properties>
    <Resources />
  </Properties>
</member>

现在,我已经编写了一个样式表,它看起来应该输出另一个XML文档,但遗憾的是,当我处理数据时,XMLNotepad2007崩溃了,IE7和Firefox3.5.5都给了我一个错误,说其中存在无限递归

如果有人能告诉我我做错了什么,我将不胜感激

<xsl:transform version="1.0">

  <xsl:output 
    method="xml" version="4.0" encoding="iso-8859-1" 
    indent="yes" media-type="text/xml" 
  />

  <xsl:variable name="AssemblyName" />

  <xsl:template match="/">
    <xsl:apply-templates select="/doc/assembly" />
  </xsl:template>

  <xsl:template match="assembly/name">
    <xsl:variable name="AssemblyName" select="text()" />
    <assembly name="{$AssemblyName}">
      <xsl:apply-templates select="/doc" />
    </assembly>
  </xsl:template>

  <xsl:template match="/doc/members/member">
    <!-- This gives you a single letter 
         (T=Type P=Property M=Method F=Field) -->
    <member type="{substring-before(@name,':')}">
      <xsl:call-template name="RecurseName">
        <!-- This gives you the type name from the beginning 
             of the Namespace to the final local name. -->
        <xsl:with-param name="Path" select="
          substring-after(substring-after(@name,':'),'.')
        " />
      </xsl:call-template>
    </member>
  </xsl:template>

  <xsl:template name="RecurseName">
    <xsl:param name="Path" select="'default'" />
    <xsl:variable name="PathRemainder" select="substring-after($Path,'.')" />
    <xsl:value-of select="$PathRemainder" />
    <xsl:element name="{substring-before($Path,'.')}">
      <xsl:if test="$PathRemainder != ''">
        <xsl:call-template name="RecurseName">
          <xsl:with-param name="Path" select="$PathRemainder" />
        </xsl:call-template>
      </xsl:if>
    </xsl:element>
  </xsl:template>

</xsl:transform>

[稍后,我将转换此文档,以便如果成员具有匹配的元素,它们将合并在一起。]

基本上,如果RecurseName模板甚至存在,并且没有任何元素,它就会使XMLNotepad2007崩溃。请注意,
是纯调试

有什么想法吗

附录A:测试XML

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="XmlDocTemplate3.xml" ?>
<doc>
  <assembly>
    <name>PrimeNumbers</name>
  </assembly>
  <members>
    <member name="T:PrimeNumbers.Properties.Resources">
      <summary>
              A strongly-typed resource class, for looking up localized strings, etc.
            </summary>
    </member>
    <member name="P:PrimeNumbers.Properties.Resources.ResourceManager">
      <summary>
              Returns the cached ResourceManager instance used by this class.
            </summary>
    </member>
    <member name="P:PrimeNumbers.Properties.Resources.Culture">
      <summary>
              Overrides the current thread's CurrentUICulture property for all
              resource lookups using this strongly typed resource class.
            </summary>
    </member>
    <member name="M:PrimeNumbers.Program.Main">
      <summary>
            The main entry point for the application.
            </summary>
    </member>
    <member name="M:PrimeNumbers.PrimeNumberForm.CalculatePrimeNumbers(System.Int32)">
      <summary>
            Calculates the prime numbers between 1 and the (count)th prime number.
            </summary>
      <param name="count">The number of prime numbers to return.</param>
      <returns>List of integers</returns>
      <exception cref="T:System.ArgumentOutOfRangeException">Thrown if <paramref name="count" /> is negative.</exception>
    </member>
    <member name="F:PrimeNumbers.PrimeNumberForm.components">
      <summary>
            Required designer variable.
            </summary>
    </member>
    <member name="M:PrimeNumbers.PrimeNumberForm.Dispose(System.Boolean)">
      <summary>
            Clean up any resources being used.
            </summary>
      <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    </member>
    <member name="M:PrimeNumbers.PrimeNumberForm.InitializeComponent">
      <summary>
            Required method for Designer support - do not modify
            the contents of this method with the code editor.
            </summary>
    </member>
  </members>
</doc>

素数
强类型资源类,用于查找本地化字符串等。
返回此类使用的缓存ResourceManager实例。
为所有线程重写当前线程的CurrentUICulture属性
使用此强类型资源类进行资源查找。
应用程序的主要入口点。
计算介于1和第(计数)个素数之间的素数。
要返回的素数的数目。
整数列表
如果为负,则抛出。
必需的设计器变量。
清理所有正在使用的资源。
如果应处置托管资源,则为true;否则,错误。
设计器支持所需的方法-不修改
此方法的内容与代码编辑器一起使用。

您在线路上遇到错误:

<xsl:element name="{substring-before($Path,'.')}">

当到达不包含点“.”的命名空间的最后一部分时

您可以将此代码段用于RecurseName模板:

<xsl:template name="RecurseName">
  <xsl:param name="Path" select="'default'"/>
  <xsl:choose>
    <xsl:when test="contains($Path, '.')">
      <xsl:element name="{substring-before($Path,'.')}">
        <xsl:call-template name="RecurseName">
          <xsl:with-param name="Path" select="substring-after($Path,'.')"/>
        </xsl:call-template>
      </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:element name="{$Path}" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

我已经测试过了。生成的输出:

<member type="T">
  <Properties>
    <Resources />
  </Properties>
</member>

我认为所讨论的无限递归错误实际上是由这个模板引起的

<xsl:template match="assembly/name">
  <xsl:variable name="AssemblyName" select="text()"/>
  <assembly name="{$AssemblyName}">
    <xsl:apply-templates select="/doc"/>
  </assembly>
</xsl:template>

在该模板中执行操作时,这将与模板本身相匹配,因为assembly元素位于doc元素之下。请尝试改为在/doc/members上选择

<xsl:template match="assembly/name">
  <xsl:variable name="AssemblyName" select="text()"/>
  <assembly name="{$AssemblyName}">
    <xsl:apply-templates select="/doc/members"/>
  </assembly>
</xsl:template>


这至少可以阻止无限递归错误。

Tim C得到了正确的答案,但是还有一些其他错误,我只是为了子孙后代而更正。方法名称中的圆括号也会破坏我的XSLT。因此,在开始递归之前,我需要将“(”和“)”之间的所有内容保留为一个元素,并将第一个“(”之前的名称字符串发送到递归模板

<xsl:transform version="1.0">
 <xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes" media-type="text/xml"/>
 <xsl:variable name="AssemblyName"/>
<xsl:template match="/">
 <xsl:apply-templates select="/doc/assembly"/>
 </xsl:template>
<xsl:template match="assembly/name">
 <xsl:variable name="AssemblyName" select="text()"/>
<assembly name="{$AssemblyName}">
 <xsl:apply-templates select="/doc/members"/>
 </assembly>
 </xsl:template>
<xsl:template match="member">
<member type="{substring-before(@name,':')}">
<xsl:choose>
<xsl:when test="contains(@name,'(')">
<params>
 <xsl:value-of select="substring-before(substring-after(@name,'('),')')"/>
 </params>
<xsl:call-template name="RecurseName">
 <xsl:with-param name="Path" select="substring-after(substring-before(substring-after(@name,':'),'('),'.')"/>
 </xsl:call-template>
 </xsl:when>
<xsl:otherwise>
<xsl:call-template name="RecurseName">
 <xsl:with-param name="Path" select="substring-after(substring-after(@name,':'),'.')"/>
 </xsl:call-template>
 </xsl:otherwise>
 </xsl:choose>
 </member>
 </xsl:template>
<xsl:template name="RecurseName">
 <xsl:param name="Path" select="'default'"/>
<xsl:choose>
<xsl:when test="contains($Path,'.')">
<xsl:element name="{substring-before($Path,'.')}">
<xsl:call-template name="RecurseName">
 <xsl:with-param name="Path" select="substring-after($Path,'.')"/>
 </xsl:call-template>
 </xsl:element>
 </xsl:when>
<xsl:otherwise>
 <xsl:element name="{$Path}"/>
 </xsl:otherwise>
 </xsl:choose>
 </xsl:template>
 </xsl:transform>


仅供参考,您可以使用Altova XML Spy或Visual Studio进行xslt调试。@markbertenshaw:Hint-没有XML版本4.0;-@Rashmi-谢谢您!对于调试,您完全正确。但是,我认为使用记事本编写XML时效率更高。另一种方法是使用:
substring before(concat($Path,'.'),'.')
。这样,被测试的字符串总是以分隔符结尾,您所需要做的就是
。遗憾的是,这段代码似乎也有递归错误。至于代码的更改,虽然我同意它更好,因为它更明确,但我的代码会更紧凑。假设字符串函数不返回空字符串(“”),并且我无法测试,这是一个基本错误吗?Rashmi-出于兴趣,您使用XSLT转换什么XML?我将发布我的文件,只是为了确定。标记我只转换了成员元素,因为您没有发布整个xml。不过,我并没有收到该代码段的任何递归错误。很高兴,你找到了解决办法:)蒂姆-你完全正确。我为自己没有发现这一点而自责。然而,即使这是固定的,也会出现一些错误。首先,我没有考虑有参数的方法会发生什么——圆括号在元素名称中是非法的。必须在与原始成员元素匹配的模板中剥离这些元素。无论如何,非常感谢。这只是第一阶段。我还有很多东西要学。干杯,马克