有没有一种有效的方法将LINQ-to-SQL数据转换为XML?

时间:2009-09-26 00:02:40

标签: asp.net-mvc linq-to-sql xslt

我正在为我的网站构建一个模板引擎。我正在使用ASP.NET MVC和Linq-to-SQL。

所以,

我想要做的是生成这样的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()
});

进入上面的模型?

2 个答案:

答案 0 :(得分: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>

答案 1 :(得分: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);
    }