代码之家  ›  专栏  ›  技术社区  ›  John Gietzen

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

  •  2
  • John Gietzen  · 技术社区  · 16 年前

    我正在考虑为我的网站构建一个模板引擎。我正在使用ASP.NETMVC和LINQtoSQL。

    我想做的是 生成如下所示的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 回复  |  直到 16 年前
        1
  •  1
  •   sipsorcery    16 年前

    我怀疑有没有一个简单的方法来实现你的目标。

    对于类似的情况,我要做的是向我的数据类中添加一个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;
    }
    

    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>
    
        2
  •  1
  •   John Gietzen    16 年前

    那么我发现这个方法,

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

    这使得创建非常简单。还有更好的吗?

    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);
        }