2009-09-26 71 views
2

我在爲我的網站構建一個模板引擎。我正在使用ASP.NET MVC和Linq-to-SQL。有沒有一種將LINQ-to-SQL數據轉換爲XML的有效方法?

所以,

什麼我想要做的是產生這樣的XML文檔:

<?xml version="1.0" encoding="utf-8" ?> 
<MainPage> 
    <MainPageHtml><![CDATA[<p>lol!</p><br/>wtf? totally!]]></MainPageHtml> 
    <Roles> 
    <Role RoleId="1">User</Role> 
    <Role RoleId="2">Administrator</Role> 
    </Roles> 
</MainPage> 

而且用XSLT轉換它像這樣

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" indent="no" encoding="iso8859-1" omit-xml-declaration="yes"/><xsl:template match="/"> 
    <xsl:value-of select="/MainPage/MainPageHtml"/> 
    <![CDATA[<select>]]><xsl:for-each select="//Roles/Role"> 
    <![CDATA[<option value="]]><xsl:value-of select="@RoleId"/><![CDATA[">]]><xsl:value-of select="."/><![CDATA[</option>]]></xsl:for-each> 
    <![CDATA[</select>]]></xsl:template> 
</xsl:stylesheet> 

使用此類代碼

XmlDocument data = new XmlDocument(); data.Load("Data.xml"); 

XslCompiledTransform transform = new XslCompiledTransform(); transform.Load("Transform.xslt"); 

StringWriter sw = new StringWriter(); 
transform.Transform(data, null, sw); 
Console.WriteLine(sw.ToString()); 

Console.ReadKey(true); 

是否有一個快速的方法來把這樣一個LINQ基於模型:

return View("MainPage", new MainPageModel 
{ 
    MainPageHtml = Config.MainPageHtml, 
    Roles = Config.GetAllRoles() 
}); 

向上面的模型?

回答

1

好吧,我發現這個方法:

 var roles = from r in db.Roles 
        orderby r.Name 
        select new XElement("Role", 
         new XAttribute("RoleId", r.RoleID), 
         r.Name); 

     var data = new XElement("MainPage", 
         new XElement("Roles", roles)); 

     return View(data); 

這使得很容易創建。有更好的嗎?

編輯:我寫了一個XSLT視圖引擎

這幾乎是我的整體解決方案:

public class XsltViewEngine : VirtualPathProviderViewEngine 
{ 
    public XsltViewEngine() 
    { 
     base.ViewLocationFormats = new string[] 
     { 
      "~/Views/{1}/{0}.xslt", 
      "~/Views/Shared/{0}.xslt", 
     }; 

     base.PartialViewLocationFormats = base.ViewLocationFormats; 
    } 

    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) 
    { 
     return new XsltViewPage(partialPath); 
    } 

    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) 
    { 
     return new XsltViewPage(viewPath); 
    } 
} 

class XsltViewPage : IView 
{ 
    protected string ViewPath { get; private set; } 

    public XsltViewPage(string viewPath) 
    { 
     this.ViewPath = viewPath; 
    } 

    public void Render(ViewContext viewContext, TextWriter writer) 
    { 
     XslCompiledTransform transform = new XslCompiledTransform(); 
     transform.Load(viewContext.HttpContext.Server.MapPath(this.ViewPath)); 

     object model = viewContext.ViewData.Model; 

     if (model == null) 
     { 
      throw new InvalidOperationException("An attempt was made to render an XSL view with a null model. This is invalid. An XSL view's model must, at very least, be an empty XML document."); 
     } 

     if(model is IXPathNavigable) 
     { 
      transform.Transform((IXPathNavigable)model, null, writer); 
     } 
     else if (model is XNode) 
     { 
      transform.Transform(((XNode)model).CreateReader(), null, writer); 
     } 
     else 
     { 
      throw new InvalidOperationException("An attempt was made to render an XSL view with an invalid model. An XSL view's model must be either an IXPathNavigable or an XNode."); 
     } 
    } 
} 

而且,在Globals.asaxcs:

protected void Application_Start() 
    { 
     ViewEngines.Engines.Add(new XsltViewEngine()); 

     RegisterRoutes(RouteTable.Routes); 
    } 
1

我懷疑有一種簡單的方法可以做你想做的事情。

我對類似的情況做了什麼是添加一個ToXML()方法到我的數據類(新行不是必需的,但有助於打印出來用於診斷目的的XML,所以我總是把它們放進去)。

public string ToXML() { 
    string xml = 
     " <provider>" + m_newLine + 
     " <id>" + m_id + "</id>" + m_newLine + 
     " <providerid>" + m_providerId + "</providerid>" + m_newLine + 
     " <providername>" + ProviderName + "</providername>" + m_newLine + 
     " </provider>"; 
    return xml; 
} 

這apporach不會爲你做整個工作,但會讓你在路上。

Roles = Config.GetAllRoles(); 
string rolesXML = "<MainPage><MainPageHtml><p>lol!</p><br/>wtf? totally!></MainPageHtml> <Roles>" 
Roles.ForEach(r => rolesXML += String.Format("<Role RoleId='{0}'>{1}</Role>", r.ID, r.Description)); 
string rolesXML += "</Roles>"; 

在您的XSL中,您不需要爲新元素添加CDATA部分。相反的:

<![CDATA[<option value="]]><xsl:value-of select="@RoleId"/><![CDATA[">]]><xsl:value-of select="."/><![CDATA[</option>]]> 

可以使用更爲清晰:

<option> 
    <xsl:attribute name="value"><xsl:value-of select="@RoleId"/></xsl:attribute> 
    <xsl:value-of select="."/> 
</option> 
+0

代碼喜歡你的第一個片段應僅用於診斷或原型設計,因爲如果輸入包含字符(例如< or >),它將創建無效的XML。使用XmlDocument,XmlWriter或XDocument APIs會更安全,因爲它們可以確保事情能夠正確地轉義。 – itowlson 2009-09-26 01:43:29

+0

在構建XML以補充任何< >或控制字符時,我使用SafeXML方法(爲簡潔起見未顯示)。使用XDocument API對我來說很笨拙,並且不會讓您直觀地感覺到生成的XML會是什麼。 – sipwiz 2009-09-26 01:54:34

+0

我不需要很好的感覺,因爲XML是中間步驟。我實際上正在尋找一種不首先序列化的方法。我希望它保持爲DOM。 (我認爲我表現出的方​​式可能會這樣做。) – 2009-09-26 03:22:09

相關問題