2011-10-26 26 views
0

を定義するためにXMLを使用したHTMLフォームの作成:私は次のスキーマにいくつかのXMLを持っていレイアウトC#の

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

私は次のように表すことになり、HTMLフォームを生成するために、C#でこれを解析する必要があります。

<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#を使用して、これをコントロールに入れて自分のページに入れることができます。

私の質問は、どうすればこのようなことを達成できますか?ノードの名前や型などをチェックするためのネストされたswitch文や、HTMLのstringbuildingが必要です。しかし、私はこれが当てはまらないことを願っています。あなたの棺は、これを正しい方向に向けるのを助けることができます。

あなたの不安を確認するために申し訳ありませんが事前に感謝:)

デイブ

+0

LINQ to XMLなどが、XSLTがオプションでない場合、より簡潔な解決策を可能にすると思われます。 –

+2

C#でXSLTを使用できます。http://msdn.microsoft.com/en-us/library/system.xml.xsl.xslcompiledtransform.aspx –

答えて

0

これを実現する1つの方法は、生成したいさまざまなHTMLエンティティを表すオブジェクトを作成することです。これは非常に簡単な例です。すべての種類のトリッキーと再利用可能な基本クラスを持つことができます。しかし、あなたは、各HTML要素のためのElement派生クラスを持っているだろう、それが問題の範囲外だと我々は両方:)

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 

明らかにここにすべての日になると思います。また、XMLノードからそれらを初期化する方法もあります。しかし今、私たちのXmlタグをDOMオブジェクトに関連付ける必要があります。私たちは、辞書を使用して(この単純なケースでは、私は再び本格的な工場を好むが、したい! - それは、この答えの範囲外です)それを行うことができます

public delegate IElement ElementCreator; 
Dictionary<string, ElementCreator> creators_ = new Dictionary<string, ElementCreator> 

を私が先に行くと1を追加します当社の要素の場合:

creators_["fieldset"] =() => { return new FieldSet(); }; 
// and so on for other creators and elements. 

もうすぐだ。次のステップは、その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これはどのように機能するかを示します。

0

が、これを行うには、「一般的な」または「単純な」方法はありません。

あなたが言及したように、XSLTは標準的な方法であり、同じことをするカスタムパーサー/ストリングビルダーのようなものを構築する必要があります。

MVCフレームワークを使用して作業負荷を軽減する方法があります。

MVCフレームワークは基本的に任意のクラスを取り、適切なHTML(これまでのビューエンジンを使用)を生成する 'オートバインダー'のような機能を備えています。

そのルートを選択した場合、タスクは単純なXMLの解析に限定され、整形式の装飾クラスが作成されます。これにより、MVCフレームワークはHTML形式のCRUDビューをすべて生成することができます。

希望は、乾杯。

0

あなたは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にファイルがあなたの元の質問で述べたとstyle.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> 

幸運のように見えるものです

関連する問題