C#递归方法出乎意料的结果

4 html c# string recursion text

我有一个相当简单的方法,递归删除开始/结束html标签

class Program
    {   
        static void Main(string[] args)
        {
            string s = FixHtml("<div><p>this is a <strong>test</strong></p></div>");
            Console.WriteLine(s);
        }

        private static string FixHtml(string s)
        {            
            //Remove any outer <div>
            if (s.ToLower().StartsWith("<div>"))
            {
                FixHtml(s.Substring(5, s.Length - 5));
            }
            else if (s.ToLower().StartsWith("<p>"))
            {
                FixHtml(s.Substring(3, s.Length - 3));
            }
            else if (s.ToLower().EndsWith("</div>"))
            {
                FixHtml(s.Substring(0, s.Length - 6));
            }
            else if (s.ToLower().EndsWith("</p>"))
            {
                FixHtml(s.Substring(0, s.Length - 4));
            }

            return s;
        }
    }
Run Code Online (Sandbox Code Playgroud)

行为是它可以递归删除<div> & <p>标签,但在"返回s"语句中它撤消所有的工作,通过添加回添加标签!

谁知道为什么会这样?以及如何强制它返回我想要的值.即
this is a <strong>test</strong>

Bev*_*van 14

在.NET中,字符串是不可变的 - 因此您的方法实际上永远不会更改返回值.当你打电话时,s.ToLower().StartsWith("<div>")你会收到一个带有预期差异的新字符串.在现有的字符串s保持不变.

此外,您永远不会消耗递归调用的返回值.

在我的头顶,尝试这样的事情:

    private static string FixHtml(string s)
    {            
        if (s.ToLower().StartsWith("<div>"))
        {
            return FixHtml(s.Substring(5, s.Length - 5));
        }
        else if (s.ToLower().StartsWith("<p>"))
        {
            return FixHtml(s.Substring(3, s.Length - 3));
        }
        else if (s.ToLower().EndsWith("</div>"))
        {
            return FixHtml(s.Substring(0, s.Length - 6));
        }
        else if (s.ToLower().EndsWith("</p>"))
        {
            return FixHtml(s.Substring(0, s.Length - 4));
        }

        return s;
    }
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 5

请注意,原始文本操作通常是处理xml的一种不好的方法 - 例如,您不处理属性,命名空间,尾随标记空白(<p >)等.

通常情况下,我会把它加载到DOM(XmlDocument/ XDocumentxhtml; HTML Agaility Pack for html)中 - 但实际上我想知道在这种情况下xslt是否会好...

例如:

static void Main()
{
    string xhtml = @"<div><p>this is a <strong>test</strong></p></div>";
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load("strip.xslt");

    StringWriter sw = new StringWriter();
    using(XmlReader xr = XmlReader.Create(new StringReader(xhtml))) {
        xslt.Transform(xr, null, sw);
    }
    string newHtml = sw.ToString();
    Console.WriteLine(newHtml);
}
Run Code Online (Sandbox Code Playgroud)

使用strip.xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no" omit-xml-declaration="yes"/>
  <xsl:template match="strong|@*">
    <xsl:copy><xsl:apply-templates select="*|text()"/></xsl:copy>
  </xsl:template>
  <xsl:template match="*">
    <xsl:apply-templates select="*|text()"/>
  </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)