2014-05-21 1 views
1

파일 시스템의 실제 파일이 아닌 사용자 정의 XmlResolver를 사용하여 XslCompiledTransform에서 문서 함수 참조를 해결하려고합니다. 구식 XslTransform을 사용하면 제대로 작동하지만 컴파일 된 변환 (성능상의 이유로 사용하고 싶음)을 사용하지 않아도됩니다.XmlResolver가 XslCompiledTransform과 함께 호출되지 않았습니다.

소스 XML 문서는 다음과 같습니다

<?xml version=""1.0"" encoding=""UTF-8""?> 
<StackOverflow> 
</StackOverflow> 

XSLT는 다음과 같습니다

<xsl:stylesheet version=""1.0"" 
       xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"" 
       xmlns:xs=""http://www.w3.org/2001/XMLSchema"" 
       exclude-result-prefixes=""xs""> 
    <xsl:variable name=""author"" select=""document('data.xml')""/> 

    <xsl:template match=""/""> 
     <StackOverflow> 
      <Author> 
       <xsl:copy-of select=""$author/Person/*""/> 
      </Author> 
     </StackOverflow> 
    </xsl:template> 
</xsl:stylesheet> 

예상 출력은 다음과 같습니다

<?xml version="1.0" encoding="utf-16"?> 
<StackOverflow> 
<Author> 
    <FirstName>Aaron</FirstName> 
    <LastName>Janes</LastName> 
</Author> 
</StackOverflow> 

내가 사용하고자하는 부분 사용자 정의 XmlResolver는 "file ('data.xml')입니다.이 파일은 디스크의 파일에서로드하고 싶지 않지만 간단하게하기 위해 상기 리졸버 내의 정적 사전, 그래서 같은 포스트의 단순성 :

namespace transform 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.IO; 
    using System.Text; 
    using System.Xml; 

    public class XmlStaticResolver : XmlResolver 
    { 
     private const string PersonXml = 
@"<?xml version=""1.0"" encoding=""utf-8""?> 
<Person> 
    <FirstName>Aaron</FirstName> 
    <LastName>Janes</LastName> 
</Person>"; 

     private readonly IDictionary<string, string> _input; 

     public XmlStaticResolver() 
     { 
      _input = new Dictionary<string, string> 
      { 
       { "data.xml", PersonXml } 
      }; 
     } 

     public override object GetEntity(Uri absoluteUri, 
             string role, 
             Type ofObjectToReturn) 
     { 
      var host = absoluteUri.Host; 
      var xml = _input[host]; 
      var bytes = Encoding.UTF8.GetBytes(xml); 
      var result = new MemoryStream(bytes); 

      return result; 
     } 

     public override Uri ResolveUri(Uri baseUri, string relativeUri) 
     { 
      return new Uri("static://" + relativeUri); 
     } 
    } 
} 

리졸버 상대 URI ("인 data.xml")을 취하고 GetEntity 방법은 "데이터를 고려하도록 가짜 프로토콜 앞에 추가 .xml "을 URL의 호스트로 사용하십시오. 그런 다음 값은 정적 사전에서 조회되고 사용할 변환의 메모리 스트림으로 반환됩니다.

나는 쓸모 XmlTransform를 사용하여이 방법을 사용하면이 (가) 상기 XSLT와 방법을 변환 호출, 예를 들어, 예상대로 정확하게 작동하고 XML은 예상 된 결과 가져옵니다 내가하려고 할 때, 그러나

namespace transform 
{ 
    using System.IO; 
    using System.Xml; 
    using System.Xml.XPath; 
    using System.Xml.Xsl; 

    public class ObsoleteTransform 
    { 
     public string Transform(string xslt, string xml) 
     { 
      var resolver = new XmlStaticResolver(); 
      var transform = new XslTransform { XmlResolver = resolver }; 
      using (var transformReader = CreateXmlReader(new StringReader(xslt), resolver)) 
      { 
       transform.Load(transformReader); 
      } 

      using (var writer = new StringWriter()) 
      { 
       using (var xwriter = CreateXmlWriter(writer)) 
       { 
        using (var inputReader = new StringReader(xml)) 
        { 
         var input = new XPathDocument(inputReader); 
         transform.Transform(input, 
              new XsltArgumentList(), 
              xwriter); 
        } 
       } 

       return writer.ToString(); 
      } 
     } 

     private static XmlReader CreateXmlReader(TextReader reader, 
               XmlResolver resolver) 
     { 
      var settings = new XmlReaderSettings 
      { 
       XmlResolver = resolver 
      }; 

      var xreader = XmlReader.Create(reader, settings, (string)null); 
      return xreader; 
     } 

     private static XmlWriter CreateXmlWriter(TextWriter writer) 
     { 
      var settings = new XmlWriterSettings 
      { 
       Indent = true, 
       IndentChars = " ", 
       NewLineChars = "\r\n" 
      }; 

      var xwriter = XmlWriter.Create(writer, settings); 
      return xwriter; 
     } 
    } 
} 

System.Xml.Xsl.XslTransformException: 
    An error occurred while loading document 'data.xml'. 

나는이 (가) XslCompiledTransform로 변환을 시도하기 위해 사용하고있는 코드는 다음과 같습니다 : 나는 예외를 얻을 XslCompiledTransform를 사용하는

namespace transform 
{ 
    using System.IO; 
    using System.Xml; 
    using System.Xml.XPath; 
    using System.Xml.Xsl; 

    public class CompiledTransform 
    { 
     public string Transform(string xslt, string xml) 
     { 
      var resolver = new XmlStaticResolver(); 
      var xsltSettings = new XsltSettings(true, true); 
      var transform = new XslCompiledTransform(); 
      using (var transformReader = CreateXmlReader(new StringReader(xslt), resolver)) 
      { 
       transform.Load(transformReader, xsltSettings, resolver); 
      } 

      using (var writer = new StringWriter()) 
      { 
       using (var xwriter = CreateXmlWriter(writer)) 
       { 
        using (var inputReader = new StringReader(xml)) 
        { 
         var input = new XPathDocument(inputReader); 
         transform.Transform(input, 
              new XsltArgumentList(), 
              xwriter); 
        } 
       } 

       return writer.ToString(); 
      } 
     } 

     private static XmlReader CreateXmlReader(TextReader reader, 
               XmlResolver resolver) 
     { 
      var settings = new XmlReaderSettings 
      { 
       XmlResolver = resolver 
      }; 

      var xreader = XmlReader.Create(reader, settings, (string)null); 
      return xreader; 
     } 

     private static XmlWriter CreateXmlWriter(TextWriter writer) 
     { 
      var settings = new XmlWriterSettings 
      { 
       Indent = true, 
       IndentChars = " ", 
       NewLineChars = "\r\n" 
      }; 

      var xwriter = XmlWriter.Create(writer, settings); 
      return xwriter; 
     } 
    } 
} 

컴파일 된 변환을 사용하면 resolver가 호출되지 않는 것 같습니다. 왜 아무 생각 없어?

답변

0

당신은 당신의 XmlStaticResolver resolver에 모두XmlReader.Create()XslCompiledTransform.Load()을 전달하고 있습니다. 두 경우 모두 PersonXml/data.xml 즉 XML을 반환합니다. 하지만 XslCompiledTransform.Load()스타일 시트의 경우 .xslt 파일 경로 인 경우 XmlStaticResolver.ResolveUri()을 Uris와 호출합니다. 어쨌든 XSL을 읽는 을 CreateXmlReader(new StringReader(xslt), resolver))으로 전달하고 싶지 않습니다. 그것은 예전의 코드에서 어떻게 작동하는지 나는 당신이 당신의 오류 System.Xml.Xsl.XslTransformException: An error occurred while loading document 'data.xml'.이 그렇지 XML 문서와 같은 스타일 문서로 data.xml을로드하려고에 실패를 말하고 찾을 것이라 생각합니다 ....

을 모르는 !

"컴파일 된 변환을 사용하면 해결자가 호출되지 않은 것 같습니다."라고 말하면서도 XmlStaticResolver.ResolveUri()을 중단 점으로 디버깅 할 수 있다고 가정하고 호출되는 위치와 인수를 확인하십시오.

관련 문제