解析aspx文件中的控件并将其转换为xml

时间:2010-06-04 07:14:29

标签: c# asp.net xml

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

例如,如果我的aspx文件包含

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

我的xml文件将是

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

5 个答案:

答案 0 :(得分:5)

Xml解析器无法理解ASP指令:&lt;%@&lt;%= etc。

您可能最好使用正则表达式来完成此操作,可能分为3个阶段。

  1. 匹配整个页面中的所有标记元素。
  2. 对于每个标记,匹配标记和控件类型。
  3. 对于匹配(2)的每个标记,匹配任何属性。
  4. 所以,从顶部开始,我们可以使用以下正则表达式:

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

    这将匹配任何没有&lt;%和&lt;的标签/并且懒得这样做(我们不想要贪婪的表达,因为我们不会正确阅读内容)。可以匹配以下内容:

    <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>
    

    希望有所帮助!

答案 1 :(得分: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);

答案 2 :(得分: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;
}

这将起作用

答案 3 :(得分:0)

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

或者,您可以使用Linq to XML加载ASPX文件并以Linq样式迭代控件。

答案 4 :(得分:0)

如果标签的代码写在多行中,我们在提取标签数据时可能会遇到问题。避免我从我们传递给上述函数的源字符串中删除了下面的换行符(内容)

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

然后我们可以使用contentRemovedNewLines而不是content。

上面的代码按我的意愿工作。还可以添加一件事。你可以调用上面的方法,如下所示,然后保存为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);

我使用了上面的修复