【发布时间】:2012-10-30 15:34:15
【问题描述】:
我有一个 XML 文件定义为:
<?xml version="1.0" encoding='UTF-8'?>
<contentlets>
<content>
<entry>
<string>link</string>
<string>http://www.myLink.com</string>
</entry>
<entry>
<string>stInode</string>
<string>0b4f59c1-6dee-4c1e-a0fb-353c34c8d372</string>
</entry>
<entry>
<string>linkType</string>
<string>Category Title</string>
</entry>
<entry>
<string>linkText</string>
<string>Title</string>
</entry>
</content>
</contentlets>
和一个 XSLT 定义为:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="html" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="@* | node()">
<div id="content" data-role="content">
<ul data-role="listview" data-inset="true" data-filter="false">
<li data-role="list-divider">Category Title</li>
<xsl:for-each select="content">
<li data-inline="false" data-icon="arrow-r" data-iconpos="right">
<a target="_blank">
<xsl:for-each select="entry">
<xsl:if test="string='link'">
<xsl:attribute name="href">
<xsl:value-of select="string[2]"/>
</xsl:attribute>
</xsl:if>
<xsl:if test="string='linkText'">
<h3>
<xsl:value-of select="string[2]"/>
</h3>
</xsl:if>
</xsl:for-each>
</a>
</li>
</xsl:for-each>
</ul>
</div>
</xsl:template>
</xsl:stylesheet>
我在 Visual Studio 2010 中成功应用了此转换,但是,我想应用此转换并将生成的 HTML 存储在字符串中。我正在使用定义如下的自定义类来执行此操作:
public class XsltTransformer
{
private readonly XslCompiledTransform xslTransform;
public XsltTransformer(string xsl)
{
try
{
xslTransform = new XslCompiledTransform();
using (var stringReader = new StringReader(xsl))
{
using (var xslt = XmlReader.Create(stringReader))
{
xslTransform.Load(xslt);
}
}
}
catch (Exception ex)
{
Log.WriteLine(ex.ToString());
}
}
public string Transform(string strXml)
{
try
{
string output = String.Empty;
using (StringReader sri = new StringReader(strXml))
{
using (XmlReader xri = XmlReader.Create(sri))
{
using (StringWriter sw = new StringWriter())
using (XmlWriter xwo = XmlWriter.Create(sw, xslTransform.OutputSettings))
{
xslTransform.Transform(xri, xwo);
output = sw.ToString();
}
}
}
return output;
}
catch (Exception ex)
{
Log.WriteLine(ex.ToString());
return String.Empty;
}
}
}
然后我调用以下命令来实际应用转换:
string strXslt = String.Empty;
string strXml = String.Empty;
using (StreamReader xsltReader = new StreamReader(Server.MapPath("~/Content/xsl/test.xslt")))
{
strXslt = xsltReader.ReadToEnd();
}
using (StreamReader xmlReader = new StreamReader(Server.MapPath("~/Content/xml/test.xml")))
{
strXml = xmlReader.ReadToEnd();
}
XsltTransformer transformer = new XsltTransformer(strXslt);
return transformer.Transform(strXml);
应用转换时,我收到“路径中的非法字符”。错误。我知道我的 XML 和 XSLT 文件以字符串的形式正确通过,但我无法弄清楚为什么在应用转换时会出现此错误。
关于是什么导致此错误的任何想法?
编辑: 这是堆栈跟踪:
[ArgumentException: Illegal characters in path.]
System.IO.Path.CheckInvalidPathChars(String path) +126
System.IO.Path.Combine(String path1, String path2) +38
System.Web.Compilation.DiskBuildResultCache.GetPreservedDataFileName(String cacheKey) +27
System.Web.Compilation.DiskBuildResultCache.GetBuildResult(String cacheKey, VirtualPath virtualPath, Int64 hashCode, Boolean ensureIsUpToDate) +14
System.Web.Compilation.BuildManager.GetBuildResultFromCacheInternal(String cacheKey, Boolean keyFromVPP, VirtualPath virtualPath, Int64 hashCode, Boolean ensureIsUpToDate) +200
System.Web.Compilation.BuildManager.GetVPathBuildResultFromCacheInternal(VirtualPath virtualPath, Boolean ensureIsUpToDate) +51
System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) +68
System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile, Boolean throwIfNotFound, Boolean ensureIsUpToDate) +111
System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean throwIfNotFound) +125
System.Web.Compilation.BuildManager.GetObjectFactory(String virtualPath, Boolean throwIfNotFound) +35
System.Web.Mvc.BuildManagerWrapper.System.Web.Mvc.IBuildManager.FileExists(String virtualPath) +9
System.Web.Mvc.BuildManagerViewEngine.FileExists(ControllerContext controllerContext, String virtualPath) +41
System.Web.Mvc.VirtualPathProviderViewEngine.GetPathFromGeneralName(ControllerContext controllerContext, List`1 locations, String name, String controllerName, String areaName, String cacheKey, String[]& searchedLocations) +150
System.Web.Mvc.VirtualPathProviderViewEngine.GetPath(ControllerContext controllerContext, String[] locations, String[] areaLocations, String locationsPropertyName, String name, String controllerName, String cacheKeyPrefix, Boolean useCache, String[]& searchedLocations) +304
System.Web.Mvc.VirtualPathProviderViewEngine.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache) +136
System.Web.Mvc.<>c__DisplayClassc.<FindView>b__b(IViewEngine e) +24
System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths) +127
System.Web.Mvc.ViewEngineCollection.FindView(ControllerContext controllerContext, String viewName, String masterName) +181
System.Web.Mvc.ViewResult.FindView(ControllerContext context) +138
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +129
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +23
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +260
System.Web.Mvc.<>c__DisplayClass1e.<InvokeActionResultWithFilters>b__1b() +19
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +177
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8836913
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
【问题讨论】:
-
考虑发布异常发生时得到的堆栈跟踪。
-
XslCompiledTransform方法和您的XsltTransformer方法(如Transform)都不会出现在堆栈跟踪中,因此看起来异常与您发布的 XSLT 特定代码无关。 -
我不能重复(在 ASP.NET MVC 4 中) - 我假设
return transformer.Transform(strXml);从具有字符串返回类型的控制器方法返回。这将返回转换后的 HTML,IE 可以完美呈现。可能检查 .xslt 和 .xml 文件上的实际编码是否与规定的编码 (utf-8) 匹配,如果文件名中有任何可转义的字符(如果它们未经过测试),请在文件路径前加上“@”前缀.xml / test.xslt. -
这是一个 ArgumentException,所以对于某些对象的 ctor,而不是传递 文件路径,你传递的是 xml 字符串!
-
@Mark:XslCompiledTransform 的 Transform 方法采用 XmlReader 和 XmlWriter 类型的参数,而不是任何字符串。据我所知,这是 Transform 方法的正确使用。
标签: xml asp.net-mvc c#-4.0 xslt