2010-06-04 93 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);