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
7
  • Consider to post the stack trace you get when the exception occurs. Commented Oct 30, 2012 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. Commented Oct 30, 2012 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. Commented Oct 30, 2012 at 16:46
  • It's an ArgumentException, so to some object's ctor instead of passing the file path you are passing xml string! Commented Oct 30, 2012 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. Commented Oct 30, 2012 at 17:10

1 Answer 1

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();
}
Sign up to request clarification or add additional context in comments.

6 Comments

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.