.NET MAUI Blazor 生成sitemap.xml时出现 EntityRef: expecting ';' 错误
.NET MAUI Blazor 生成sitemap.xml时出现 EntityRef: expecting ';' 错误
兄弟,你遇到的这个EntityRef: expecting ';'错误我之前帮好几个开发者排查过,本质上就是Blazor的Razor模板解析逻辑和XML语法的冲突搞出来的问题,咱们一步步来解决:
为什么会出这个错?
Blazor的Razor编译器默认会把页面里的内容当成HTML来解析,而你直接在Razor页面里写XML声明和标签时,编译器会误把XML里的一些语法(比如属性里的特殊字符、XML声明的格式)当成Razor/HTML的语法来处理,尤其是当XML里有未转义的特殊字符(比如&),或者编译器把XML标签当成HTML标签解析时,就会抛出这个实体引用的错误。
解决方案1:在Blazor页面里正确输出XML
如果你还是想用Blazor页面来生成sitemap,得做两个关键调整:
- 用
@Html.Raw()包裹整个XML内容,告诉Razor编译器不要解析这段内容,直接输出原始文本 - 通过
IHttpContextAccessor设置响应的Content-Type为application/xml,确保浏览器和服务器都把内容当成XML处理
修改后的代码大概是这样:
@page "/sitemap1" @inject IHttpContextAccessor httpContextAccessor @using Microsoft.AspNetCore.Mvc @* 用Html.Raw避免Razor解析XML语法 *@ @Html.Raw(@"<?xml version='1.0' encoding='UTF-8' ?> <urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9""> <url> <loc>https://your-app-domain.com/</loc> <lastmod>2024-05-20</lastmod> <changefreq>daily</changefreq> <priority>1.0</priority> </url> <!-- 可以继续添加更多url节点 --> </urlset>") @code { protected override void OnInitialized() { base.OnInitialized(); // 强制设置响应类型为XML,避免默认的text/html导致解析问题 if (httpContextAccessor.HttpContext != null) { httpContextAccessor.HttpContext.Response.ContentType = "application/xml; charset=utf-8"; } } }
解决方案2:用最小API端点生成sitemap(更推荐)
如果觉得在Blazor页面里折腾太麻烦,直接在Program.cs里加一个最小API端点来输出XML会更可靠,完全绕过Razor的解析逻辑:
var app = builder.Build(); // 先注册IHttpContextAccessor(如果还没注册的话) builder.Services.AddHttpContextAccessor(); // 其他中间件配置(比如app.UseRouting()、app.UseAuthorization()等) // 添加sitemap.xml的端点 app.MapGet("/sitemap.xml", (IHttpContextAccessor httpContextAccessor) => { // 这里可以动态生成url节点,比如从数据库/配置里读取路由 var sitemapContent = @"<?xml version='1.0' encoding='UTF-8' ?> <urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9""> <url> <loc>https://your-app-domain.com/</loc> <lastmod>2024-05-20</lastmod> <changefreq>daily</changefreq> <priority>1.0</priority> </url> <url> <loc>https://your-app-domain.com/about</loc> <lastmod>2024-05-19</lastmod> <changefreq>weekly</changefreq> <priority>0.8</priority> </url> </urlset>"; httpContextAccessor.HttpContext.Response.ContentType = "application/xml; charset=utf-8"; return Results.Content(sitemapContent, "application/xml; charset=utf-8"); }); app.Run();
额外注意点
不管用哪种方式,一定要确保XML里的特殊字符(比如&、<、>、")都被正确转义成XML实体(比如&、<、>、")。如果是动态生成loc节点的内容,记得用System.Security.SecurityElement.Escape()或者System.Net.WebUtility.HtmlEncode()来处理,比如:
var rawUrl = "https://your-app-domain.com/page?param1=value¶m2=another"; var encodedUrl = System.Security.SecurityElement.Escape(rawUrl); // 输出的encodedUrl会变成 https://your-app-domain.com/page?param1=value&param2=another
这样就能彻底避免实体引用的错误了!
内容来源于stack exchange




