2009-09-26 65 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

相关问题