2010-06-04 97 views
2

我需要解析aspx文件(来自磁盘,而不是浏览器中呈现的那个文件),并列出所有存在于服务器端的asp.net控件该页面,然后从中创建一个xml文件。这将是最好的办法吗?另外,有没有可用的库?解析aspx文件中的控件并将其转换为xml

对于例如,如果我的aspx文件中包含

<asp:label ID="lbl1" runat="server" Text="Hi"></asp:label>

我的XML文件是

<controls>
<ID>lbl1</ID>
<runat>server</runat>
<Text>Hi</Text>
</controls>

+0

你说的意思是“本”在你的最后一个问题(“此外,是否有这方面的任何可用的库?”)?解析XML( - >是,有(堆)库)或在(有效的)ASPX文件中找到控件( - >不太确定是否有库)。 – scherand 2010-06-04 08:27:13

+0

“我”的意思是,任何已有的库都可以直接完成这个任务,而不是我为它编写逻辑。 – Ubaid 2010-06-04 08:36:30

回答

5

XML解析器想不明白的ASP指令:<%@ <%=等

你可能最好使用正则表达式来做到这一点,可能会在3个阶段。

  1. 匹配整个页面的任何标签元素。
  2. 对于每个标签,匹配标签和控制类型。
  3. 对于每个匹配(2)的标签,匹配任何属性。

所以,从顶部开始,我们可以使用下面的正则表达式:

(?<tag><[^%/](?:.*?)>) 

这将匹配没有<%和<任何标签/和不那么懒洋洋地(我们不”不要贪婪的表达,因为我们不会正确读取内容)。下面可以匹配:

<asp:Content ID="ph_PageContent" ContentPlaceHolderID="ph_MainContent" runat="server"> 
<asp:Image runat="server" /> 
<img src="/test.png" /> 

对于每一个被俘虏的标签,我们要然后提取标签和类型:

<(?<tag>[a-z][a-z1-9]*):(?<type>[a-z][a-z1-9]*) 

创建命名捕捉组,使这更容易,这将让我们轻松提取标签和类型。这只会匹配服务器标签,因此标准的html标签将在此时被删除。

<asp:Content ID="ph_PageContent" ContentPlaceHolderID="ph_MainContent" runat="server"> 

将产生:

{ tag = "asp", type = "Content" } 

用相同的标签,我们可以匹配任何属性:

(?<name>\S+)=["']?(?<value>(?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']? 

其中产量:

{ name = "ID", value = "ph_PageContent" }, 
{ name = "ContentPlaceHolderID", value = "ph_MainContent" }, 
{ name = "runat", value = "server" } 

所以把所有的在一起,我们可以创建一个快速的功能能为我们创造一个XmlDocument:

public XmlDocument CreateDocumentFromMarkup(string content) 
{ 
    if (string.IsNullOrEmpty(content)) 
    throw new ArgumentException("'content' must have a value.", "content"); 

    RegexOptions options = RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase; 
    Regex tagExpr = new Regex("(?<tag><[^%/](?:.*?)>)", options); 
    Regex serverTagExpr = new Regex("<(?<tag>[a-z][a-z1-9]*):(?<type>[a-z][a-z1-9]*)", options); 
    Regex attributeExpr = new Regex("(?<name>\\S+)=[\"']?(?<value>(?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?", options); 

    XmlDocument document = new XmlDocument(); 
    XmlElement root = document.CreateElement("controls"); 

    Func<XmlDocument, string, string, XmlElement> creator = (document, name, value) => { 
    XmlElement element = document.CreateElement(name); 
    element.InnerText = value; 

    return element; 
    }; 

    foreach (Match tagMatch in tagExpr.Matches(content)) { 
    Match serverTagMatch = serverTagExpr.Match(tagMatch.Value); 

    if (serverTagMatch.Success) { 
     XmlElement controlElement = document.CreateElement("control"); 

     controlElement.AppendChild(
     creator(document, "tag", serverTagMatch.Groups["tag"].Value)); 
     controlElement.AppendChild(
     creator(document, "type", serverTagMatch.Groups["type"].Value)); 


     XmlElement attributeElement = document.CreateElement("attributes"); 

     foreach (Match attributeMatch in attributeExpr.Matches(tagMatch.Value)) { 
     if (attributeMatch.Success) { 
      attributeElement.AppendChild(
      creator(document, attributeMatch.Groups["name"].Value, attributeMatch.Groups["value"].Value)); 
     } 
     } 

     controlElement.AppendChild(attributeElement); 
     root.AppendChild(controlElement); 
    } 
    } 

    return document; 
} 

得到的文件看起来是这样的:

<controls> 
    <control> 
    <tag>asp</tag> 
    <type>Content</type> 
    <attributes> 
     <ID>ph_PageContent</ID> 
     <ContentPlaceHolderID>ph_MainContent</ContentPlaceHolderID> 
     <runat>server</runat> 
    </attributes> 
    </control> 
</controls> 

希望帮助!

+0

嵌入式用户控件如何?从那里的控件将不会被您的程序记录。 +1解决方案 – 2010-06-04 08:31:31

+0

感谢马修,我很快检查一下。太感谢了! – Ubaid 2010-06-04 08:38:39

+0

@Yauheni,对于用户控件,你不会解析.ascx文件吗? – 2010-06-04 09:17:15

0

ASPX文件应该是有效的XML,所以也许XSLT将是一个很好的解决方案。 W3 Schools site有很好的介绍和参考。然后,您可以从简单的程序中调用此XSLT来选择所需的文件。

或者,您可以使用Linq to XML加载ASPX文件并在Linq风格中迭代控件。

+0

感谢您的回复,但是您是否有任何带有示例代码/示例项目的网站开始使用?我是一个完整的newbee .net :) – Ubaid 2010-06-04 08:28:20

+0

当我XDocument.Parse我得到名称不能与'%'字符。页面始于'<%@ Control Language =“C#”AutoEventWireup =“true”CodeFile =“DealSummary.ascx.cs”Inherits =“Pages_UserControls_DealSummary”%> – Maslow 2011-06-20 20:19:29

+2

没有要求aspx页面成为有效的XML。页面或控制指令本身将导致此方法失败 – GavinB 2013-09-15 09:07:33

1
Func<XmlDocument, string, string, XmlElement> creator = (document, name, value) => { 
XmlElement element = document.CreateElement(name); 
element.InnerText = value; 

上述通用模板将工作version 3.5及以上..因此,如果使用以下版本的任何一个,创建功能,如:

public XmlElement creator(XmlDocument document, string name, string value) 
{ 
    XmlElement element = document.CreateElement(name); 
    element.InnerText = value; 

    return element; 
} 

这将工作

0

如果该代码标签被写入多行,我们可能在提取标签数据时遇到问题。避免我已删除从我们传递于上述功能(内容)的源串,如下换行符

string contentRemovedNewLines = Regex.Replace(content, @"\t|\n|\r", ""); 

那么我们可以使用,而不是内容contentRemovedNewLines。

上面的代码正常工作。还可以添加一件东西。你可以调用上面的方法,如下所示,然后保存为一个XML文件,所以我们可以检查预期的结果是否存在。

XmlDocument xmlDocWithWebContent = CreateDocumentFromMarkup(sourceToRead); 

string xmlfileLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "tempXmlOutputFileOfWebSource.xml"; 

xmlDocWithWebContent.Save(xmlfileLocation); 

要做到这一点,我们必须有XML文件根元素

  XmlDocument document = new XmlDocument(); 
      XmlNode xmlNode = document.CreateNode(XmlNodeType.XmlDeclaration, "", ""); 
      XmlElement root = document.CreateElement("controls"); 
      document.AppendChild(root); 

我使用上述修正为

2

我用下面的三个常规表达式与上述代码,它也给我html标签。我也可以在开始和结束标签之间获得值。

Regex tagExpr = new Regex("(?<tag><[^%/](?:.*?)>[^/<]*)", options); 
Regex serverTagExpr = new Regex("<(?<type>[a-z][a-z1-9:]*)[^>/]*(?:/>|[>/])(?<value>[^</]*)", options); 
Regex attributeExpr = new Regex("(?<name>\\S+)=[\"']?(?<value>(?:.(?![\"']?\\s+(?:\\S+)=|[>\"']))+.)[\"']?", options);