1

我有一个 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
4

1 回答 1

1

代替:

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

和:

<xsl:element name="a">
    <xsl:attribute name="target">
        <xsl:text>_blank</xsl:text>
    </xsl:attribute>
    <xsl:if test="./entry/string[1]/text()[.='link']">
        <xsl:attribute name="href">
            <xsl:value-of select="(./entry[./string[1]/text()='link']/string[2]/text())[1]"/>
        </xsl:attribute>
    </xsl:if>
    <xsl:if test="./entry/string[1]/text()[.='linkText']">
        <xsl:element name="h3">
            <xsl:value-of select="(./entry[./string[1]/text()='linkText']/string[2]/text())[1]"/>
        </xsl:element>
    </xsl:if>
</xsl:element>

附言。我也会改变

using (StringWriter sw = new StringWriter())
using (XmlWriter xwo = XmlWriter.Create(sw, xslTransform.OutputSettings))
{
    xslTransform.Transform(xri, xwo);
    output = sw.ToString();
}

using (StringWriter sw = new StringWriter())
{
    using (XmlWriter xwo = XmlWriter.Create(sw, xslTransform.OutputSettings))
    {
        xslTransform.Transform(xri, xwo);
    }
    output = sw.ToString();
}
于 2012-10-31T23:34:40.883 回答