我需要解析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>
答案 0 :(得分:5)
Xml解析器无法理解ASP指令:&lt;%@&lt;%= etc。
您可能最好使用正则表达式来完成此操作,可能分为3个阶段。
所以,从顶部开始,我们可以使用以下正则表达式:
(?<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);
我使用了上面的修复