使用XML创建HTML表单来定义布局c#
本文关键字:定义 布局 表单 XML 创建 HTML 使用 | 更新日期: 2023-09-27 18:12:21
我在下面的模式中有一些XML:
<Form ID="1" Formtitle="Title">
<Fields>
<Fieldset Legend="LegendText" >
<Field FieldName="Field1" Label="Title" Type="Text" Required="1" />
<Field FieldName="Field2" Label="Radio" Type="Radio" Required="0">
<Option Value="1" Text="Just One"/>
<Option Value="2" Text="Maybe Two"/>
</Field>
</Fieldset>
</Fields>
</Form>
我需要在c#中解析它,以生成一个表示以下内容的HTML表单:
<h1>Formtitle</h1>
<form id="1" action="myurl.com">
<fieldset>
<legend>LegendText</legend>
<label>Title</label>
<input type="text" name="Field1" class="jqueryValidate"/>
<!-- jqueryvalidate class added as required is equal to 1 in XML -->
<label>Radio</label>
<input type="radio" name="Field2" Value="1"/> Just One
<input type="radio" name="Field2" Value="2"/> Maybe Two
</fieldset>
</form>
现在,我知道我可以使用XSLT实现同样的事情,但是我必须在这里使用c#,因为我将把它包装成一个控件,我可以把它放到任何页面中。
我的问题是,我怎样才能实现这样的事情?我设想它需要某种类型的嵌套开关语句来检查节点名称和类型等,以及HTML的字符串构建。但是,我希望情况不是这样,你们这些科学家可以帮我指出正确的方向。
Thanks in advance:)
戴夫实现这一点的一种方法是设计一些对象来表示您想要生成的各种HTML实体。注意,这是一个非常非常简化的例子。你可以有一个基类,里面有各种技巧和可重用性。但这超出了问题的范围,我们都要在这里呆一整天。
public interface IElement
{
string RenderStart();
string RenderEnd();
string Render();
IList<IElement> Children { get; }
void LoadFromXML(XmLReader reader);
} // eo interface IElement
public abstract class Element : IElement
{
List<IElement> children_ = new List<IElement>();
public List<IElement> Children { get { return children_; } }
public string Render()
{
StringBuilder builder = new StringBuilder(RenderStartTag());
foreach(IElement e in children_)
builder.Append(e.Render());
builder.Append(RenderEndTag());
return builder.ToString();
}
} // eo class Element
public class FieldSetElement : Element
{
public string RenderStart()
{
StringBuilder builder = new StringBuilder();
builder.Append("<fieldset legend='"")
.Append("'">");
return builder.ToString();
}
public string RenderEnd()
{
return ("</fieldset>");
}
public string Legend {get; set; }
public void LoadFromXml(XmlReader reader)
{
Legend = reader.GetAttribute("legend");
} // eo LoadFromXml
} // eo class FieldSet
显然,每个HTML元素都有一个Element
派生类。我们还有一种从Xml节点初始化它们的方法。但是现在,我们需要将Xml标记与DOM对象关联起来。我们可以使用字典(在这个简单的例子中)来实现。我更喜欢一个完全成熟的工厂,但再次-这超出了这个答案的范围!
public delegate IElement ElementCreator;
Dictionary<string, ElementCreator> creators_ = new Dictionary<string, ElementCreator>
我将继续为我们的FieldSet
元素添加一个:
creators_["fieldset"] = () => { return new FieldSet(); };
// and so on for other creators and elements.
Ok !我们就快到了。下一步是将该XML文档转换为对象。我假设现在我们有一个根对象。我将其命名为Html
(令人惊讶的名字!)你可以猜到,它也来源于Element
。它将作为我们的根节点。
Html root = new Html();
现在,我们需要一个函数来读取Xml并将其转换为当前父节点。
XmlReader reader = new XmlReader("layout.xml");
Stack<IElement> currentRoot = new Stack<IElement>();
currentRoot.Push(root);
while(reader.Read())
{
// get the element tag
if(reader.NodeType == XmlNodeType.Element)
{
Debug.Assert(creators_.ContainsKey(reader.Name)); // must have it!
IElement newElement = creators_[reader.Name].Invoke(); // create it
newElement.LoadFromXml(reader); // tell element to read itself in
currentRoot.Peek().Children.Add(newElement); // add to parent
currentRoot.Push(newElement); // we are now new parent
}
else if(reader.NodeType == XmlNodeType.EndElement)
currentRoot.Pop(); // just pop it off!
}
哇!我们基本上做完了。至此,我们有了一个对象集合!剩下的就是渲染它们了。
string html = root.Render();
BAM。我们做完了。
如果代码中有任何错误,我很抱歉,我会试着检查一遍。我没有运行过这个,但我以前做过类似的事情。我也不是说这是最好的方法,我相信还有其他的方法。这是一种方法。出于简洁的原因,我没有呈现属性,但我很乐意添加另一个具体的Element
示例来展示如何工作。
很抱歉证实你的担心,但没有"通用"或"简单"的方法来做到这一点。
正如您所提到的,XSLT是标准实践,如果做不到这一点,您就需要构建某种自定义解析器/字符串构建器来做同样的事情。
我想到的一种方法就是使用MVC框架来减少你的工作量。
MVC框架具有类似于"autobinder"的功能,基本上可以接受任何类并生成适当的HTML(使用任何视图引擎)。
因此,如果您选择了这条路线,那么您的任务将仅限于简单地解析XML并创建格式良好的注释装饰类。然后MVC框架将能够在HTML中为您生成所有CRUD视图。
希望有帮助,干杯。
我不知道您对使用XSLT有多反感,但是您可以通过在c#中使用以下XSLT来实现这一点。
using System.Xml.Xsl;
namespace XmlTransform
{
class Program
{
static void Main(string[] args)
{
// Load the style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(@"C:'style.xsl");
// Execute the transform and output the results to a file.
xslt.Transform(@"C:'input.xml", @"C:'result.html");
Console.WriteLine("Result saved to C:'result.html");
Console.ReadLine();
}
}
}
其中input.xml文件是您在原始问题中所述的内容和样式。XSL看起来像这样
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:template match="/Form">
<html>
<body>
<h1><xsl:value-of select="@Formtitle"/></h1>
<form id="1" action="myurl.com">
<fieldset>
<legend><xsl:value-of select="Fields/Fieldset/@Legend"/></legend>
<label>Title</label>
<xsl:for-each select="Fields/Fieldset/Field">
<xsl:if test="@Type = 'Text'">
<xsl:if test="@Required='1'">
<input type="text" name="{@FieldName}" class="jqueryValidate"/>
</xsl:if>
<xsl:if test="@Required='0'">
<input type="text" name="{@FieldName}"/>
</xsl:if>
</xsl:if>
<xsl:if test="@Type = 'Radio'">
<xsl:if test="@Required='1'">
<label><xsl:value-of select="@Label"/></label>
<input type="radio" name="{FieldName}"/>" class="jqueryValidate"/>
</xsl:if>
<xsl:if test="@Required='0'">
<label><xsl:value-of select="@Label"/></label>
<xsl:for-each select="Option">
<input type="radio" name="Field2" Value="1"/> Just One
</xsl:for-each>
</xsl:if>
</xsl:if>
</xsl:for-each>
</fieldset>
</form>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
祝你好运!