1

I have an XML file defined as:

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

and an XSLT defined as:

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

I am successful in applying this transformation in Visual Studio 2010, however, I want to apply this transformation and store the resulting HTML in a string. I am doing this with a custom class defined as follows:

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

I then call the following to actually apply the transformation:

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

When applying the transformation I am getting an "Illegal characters in path." error. I know that my XML and XSLT files are coming through correctly as strings I just can't figure out why I am getting this error when applying the transformation.

Any ideas as to whats causing this error?

EDIT: Here is the stack trace:

[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
  • Consider to post the stack trace you get when the exception occurs. – Martin Honnen Oct 30 '12 at 15:51
  • 1
    Neither `XslCompiledTransform` methods nor your `XsltTransformer` methods like `Transform` appear in the stack trace so it does not look like the exception is related to the XSLT specific code you posted. – Martin Honnen Oct 30 '12 at 16:34
  • 1
    I can't repeat (in ASP.NET MVC 4) - I've assumed that `return transformer.Transform(strXml);` returns from a controller method which has a string return type. This returns the transformed HTML, which IE renders flawlessly. Possibly check that the actual encodings on your .xslt and .xml files match the stated encodings (utf-8), and prefix your file paths with '@' if there are any escapable characters in your file names, if they aren't test.xml / test.xslt. – StuartLC Oct 30 '12 at 16:46
  • It's an ArgumentException, so to some object's *ctor* instead of passing the *file path* you are passing *xml string*! – VJAI Oct 30 '12 at 16:55
  • @Mark: The Transform method of XslCompiledTransform is taking parameters of type XmlReader and XmlWriter, not any strings. As far as I am aware this is the correct use of the Transform method. – Christopher.Cubells Oct 30 '12 at 17:10
  • @nonnb: You are correct, I simply want to return a string of the HTML results of the transformation to a View and I am actually performing the transformation in the Controller. I will double check the encoding, but the file paths are correct as the strings are storing the XML and XSLT correctly. – Christopher.Cubells Oct 30 '12 at 17:13
  • @Martin Honnen: If I comment out this line: `xslTransform.Transform(xri, xwo);` in XsltTransformer.Transform() method I no longer get the error. I'm not sure why my try/catch is not catching this but I am certain it must be coming from the Transform method of XslCompiledTransform class. – Christopher.Cubells Oct 30 '12 at 17:21

1 Answers1

1

Replace:

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

With:

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

ps. I'd also change

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

to

using (StringWriter sw = new StringWriter())
{
    using (XmlWriter xwo = XmlWriter.Create(sw, xslTransform.OutputSettings))
    {
        xslTransform.Transform(xri, xwo);
    }
    output = sw.ToString();
}
JohnLBevan
  • 22,735
  • 13
  • 96
  • 178
  • I still am getting the same 'Illegal characters in path.' error. The only time I can get the transform to work is if I call `xslTransform.Transform()` so that it outputs it to a file. Anytime I call Transform() so that it outputs the transformation to some kind of Stream is when I am getting this error. Any other thoughts why this works when outputting to a file and not to a Stream? – Christopher.Cubells Nov 01 '12 at 14:34
  • A guess - try checking the file encoding matches the XML's declared encoding (i.e. UTF-8) and if that's not the issue specify the encoding when reading data in / pushing it out. Also add an xml declaration to your output XML to ensure the encoding's specified there too. I would knock up the code for you to test this theory but sadly won't have a chance until the weekend. . . – JohnLBevan Nov 01 '12 at 16:58
  • I've confirmed both XML and XSLT files are encoded in UTF-8 as well as reading the data into a `StreamReader` with `System.Text.UTF8Encoding()`. I've also tried transforming with different output settings to output in HTML or XML with and without the XML declaration. Still getting the 'Illegal characters in path' error. I appreciate your help, any other ideas? – Christopher.Cubells Nov 01 '12 at 17:28
  • Just reread your question / with the stack trace - the stack trace isn't coming from the transform code - also it's not complete; everything in there refers to system libraries - I would have expected at least one line of it to refer to your code? You mentioned you get the error when applying the transformation - do you mean that the line which throws the error is that line, or do you mean the error is thrown at some point but only when the transformation line's included? – JohnLBevan Nov 01 '12 at 17:37
  • I really have no idea where the error is being thrown, it's not being caught at all in my code even with the try/catch. However, when I comment out `xslTransform.Transform(xri, xwo)` the error is no longer thrown. So yes, the error is being thrown at some point but only when the transformation line is included. – Christopher.Cubells Nov 01 '12 at 18:26
  • I'm out of ideas, but found a couple of similar threads on here: http://stackoverflow.com/questions/4738331/entity-framework-illegal-characters-in-path-connection-string-mvc3 or http://stackoverflow.com/questions/12889456/mvc-3-stops-working-after-mvc4-installation – JohnLBevan Nov 02 '12 at 00:05