2009-06-15 7 views
5

.NET 2.0/VS2005एक्सएसएल को कैसे हल करें एक ट्रांसफॉर्मेशन में शामिल है जो स्ट्रिंग से एक्सएसएल लोड करता है?

मैं एक XSL परिवर्तन प्रदर्शन करने के लिए XslCompiledTransform वर्ग का उपयोग करने की कोशिश कर रहा हूँ।

Main.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:include href="Included.xsl" /> 
    ... 
    ... 
</xsl:stylesheet> 

अब, अगर मैं लोड कर सकता है "मुख्य मैं दो XSL फ़ाइलें, जिनमें से पहले एक <xsl:include> बयान के रूप में अन्य के लिए एक संदर्भ भी शामिल है .xsl "यूआरआई के रूप में फाइल, मेरे परिवर्तन कोड के रूप में सरल होगा:

// This is a function that works. For demo only. 
private string Transform(string xslFileURI) 
{ 
    XslCompiledTransform xslt = new XslCompiledTransform(); 

    // This load works just fine, if I provide the path to "Main.xsl". 
    // The xsl:include is automatically resolved. 
    xslTransform.Load(xslFileURI); 

    StringWriter sw = new StringWriter(); 
    xslt.Transform(Server.MapPath("~/XML/input.xml"), null, sw); 
    return sw.ToString(); 
} 

समस्या यह है कि मैं एक स्ट्रिंग के रूप Main.xsl फ़ाइल की सामग्री को प्राप्त करते हैं और एक के रूप में स्ट्रिंग लोड करने के लिए की जरूरत है XmlReader/IXpathNavigableइस समय यह एक आवश्यक प्रतिबंध है। जब मैं XmlReader/XpathDocument का उपयोग करके ऐसा करने का प्रयास करता हूं, तो यह विफल रहता है क्योंकि कोड C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ फ़ोल्डर में "include.xsl" ढूंढता है! जाहिर है, XmlResolver सापेक्ष यूआरएल को हल करने में सक्षम नहीं है क्योंकि यह केवल इनपुट एक्सएसएल के रूप में एक स्ट्रिंग प्राप्त करता है।

इस दिशा में मेरे प्रयासों देखो की तरह:

// This doesn't work! Halp! 
private string Transform(string xslContents) 
{ 
    XslCompiledTransform xslt = new XslCompiledTransform(); 
    XmlUrlResolver resolver = new XmlUrlResolver(); 
    resolver.Credentials = CredentialCache.DefaultCredentials; 

    //METHOD 1: This method does not work. 
    XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.XmlResolver = resolver; 
    XmlReader xR = XmlReader.Create(new StringReader(xslContents), settings); 
    xslt.Load(xR); // fails 

    // METHOD 2: Does not work either. 
    XPathDocument xpDoc = new XPathDocument(new StringReader(xslContents)); 
    xslt.Load(xpDoc, new XsltSettings(true, true), resolver); //fails. 

    StringWriter sw = new StringWriter(); 
    xslt.Transform(Server.MapPath("~/XML/input.xml"), null, sw); 
    return sw.ToString(); 
} 

मैं शामिल होने के लिए XSL फ़ाइल को संदर्भित एक Stream प्राप्त करने के लिए XmlUrlResolver की ResolveUri विधि का उपयोग करने की कोशिश की है, लेकिन कैसे के रूप में उलझन में हूँ इस स्ट्रीम का उपयोग करने के लिए। IOW, मैं कैसे XslCompiledTransform वस्तु बताऊँ Main.xsl XmlReader के अलावा इस धारा का उपयोग करें:

Uri mainURI = new Uri(Request.PhysicalApplicationPath + "Main.xsl"); 
Uri uri = resolver.ResolveUri(mainURI, "Included.xsl"); 

// I can verify that the Included.xsl file loads in the Stream below. 
Stream s = resolver.GetEntity(uri, null, typeof(Stream)) as Stream; 

// How do I use this Stream in the function above?? 


किसी भी मदद की बहुत सराहना कर रहा है। लंबी पोस्ट के लिए क्षमा करें!

[FileNotFoundException: Could not find file 'C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\Included.xsl'.] 
    System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) +328 
    System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) +1038 
    System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize) +113 
    System.Xml.XmlDownloadManager.GetStream(Uri uri, ICredentials credentials) +78 
    System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn) +51 
    System.Xml.Xsl.Xslt.XsltLoader.CreateReader(Uri uri, XmlResolver xmlResolver) +22 
    System.Xml.Xsl.Xslt.XsltLoader.LoadStylesheet(Uri uri, Boolean include) +33 
    System.Xml.Xsl.Xslt.XsltLoader.LoadInclude() +349 
    System.Xml.Xsl.Xslt.XsltLoader.LoadRealStylesheet() +704 
    System.Xml.Xsl.Xslt.XsltLoader.LoadDocument() +293 
    System.Xml.Xsl.Xslt.XsltLoader.LoadStylesheet(XmlReader reader, Boolean include) +173 
+0

मैं आपके प्रश्न की आवश्यकता के समान कुछ पर काम कर रहा हूं और मुझे एक एमएसडीएन लेख मिला - [अज्ञात हल करना: .NET Framework में कस्टम XmlResolvers बनाना] (http://msdn.microsoft.com/en-us/ लाइब्रेरी/aa302284.aspx) - ऐसा लगता है कि यह एक बहुत ही आशाजनक समाधान प्रदान करता है। –

उत्तर

2

मैं शायद स्पष्ट याद आ रही है लेकिन वहाँ एक कारण है तुम सिर्फ परिवर्तन नहीं करते Included.xsl के URI एक सच्चे यूआरएल के लिए:

आपके संदर्भ के लिए, अपवाद StackTrace इस तरह दिखता है ? यह या तो एक्सएसएल दस्तावेज़ में किया जा सकता है यदि आपके पास स्ट्रिंग मैनिपुलेशन का उपयोग या उपयोग किया जाता है?

+0

डेविड: उत्तर के लिए धन्यवाद। इसका कारण यह है कि मैं सामान्य नियम के रूप में, एप्लिकेशन में कहीं भी किसी भी पथ को हार्ड कोड नहीं कर सकता। इस मामले में, यह मेरा आखिरी उपाय होगा। ;-) – Cerebrus

+0

मुझे यकीन नहीं है कि इससे बचा जा सकता है। स्ट्रीम उदाहरण काम करता है क्योंकि आप Main.xsl को उसी भौतिक स्थान से Include.xsl के रूप में लोड कर रहे हैं। इसलिए स्ट्रिंग मैनिपुलेशन पर वापस जाकर आप केवल यूआरआई पर Request.PhysicalApplicationPath जोड़ सकते हैं अन्यथा, कोड को कैसे पता चलेगा कि Include.xsl को कहां देखना है? जब आप स्ट्रिंग टीएनएक्स –

+0

हम्म से आ रहे हैं तो अतिरिक्त पॉइंटर की आवश्यकता होगी ... मैं कस्टम XmlUrlResolver (जो क्लीनर तरीका था) प्राप्त करके इसे करने में असमर्थ था। समय की बाधाओं के कारण, मुझे स्ट्रिंग मैनिपुलेशन के माध्यम से ऐसा करना होगा। विचार के लिए धन्यवाद। – Cerebrus

5

एक कस्टम XmlUrlResolver

class MyXmlUrlResolver : XmlUrlResolver 
    { 
     public override Uri ResolveUri(Uri baseUri, string relativeUri) 
     { 
      if (baseUri != null) 
       return base.ResolveUri(baseUri, relativeUri); 
      else 
       return base.ResolveUri(new Uri("http://mypath/"), relativeUri); 
     } 
    } 

का प्रयोग करें और XslCompiledTransform का भार समारोह में इसका इस्तेमाल करते हैं,

resolver=new MyXmlUrlResolver(); 
xslt.Load(xR,null,resolver); 
+0

कार्तिक: उत्तर के लिए धन्यवाद। यह वह दिशा है जिसे मैं वर्तमान में पीछा कर रहा हूं। मैं सोच रहा हूं कि कस्टम XmlUrlResolver में "http: // mypath /" भाग को हार्ड कोडिंग से बचने का कोई तरीका है या नहीं। कोई विचार ? – Cerebrus

+0

यह कॉन्फ़िगर करने योग्य पैरामीटर हो सकता है या यदि यह उसी सर्वर पर होस्ट किया गया है तो Server.MapPath का उपयोग करें। बीटीडब्लू, आप मेन.एक्सएसएल कैसे प्राप्त करते हैं? HTTP पथ तक पहुंचकर? – Gee

2

जी के जवाब का उल्लेख के रूप में, आप एक कस्टम XmlResolver (जिनमें से XmlUrlResolver पहले से ही प्राप्त होता है का उपयोग करना चाहते), लेकिन यदि आप GetEntity विधि को ओवरराइड करते हैं तो आप प्राथमिक XSLT दस्तावेज़ में संदर्भों को मजेदार और रोचक तरीकों से हल कर सकते हैं। कैसे आप Included.xsl के संदर्भ में हल कर सकता है की एक जानबूझकर सरल उदाहरण:

public class CustomXmlResolver : XmlResolver 
{ 
    public CustomXmlResolver() { } 

    public override ICredentials Credentials 
    { 
     set { } 
    } 

    public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) 
    { 
     MemoryStream entityStream = null; 

     switch (absoluteUri.Scheme) 
     { 
      case "custom-scheme": 

       string absoluteUriOriginalString = absoluteUri.OriginalString; 
       string ctgXsltEntityName = absoluteUriOriginalString.Substring(absoluteUriOriginalString.IndexOf(":") + 1); 
       string entityXslt = ""; 

       // TODO: Replace the following with your own code to load data for referenced entities. 
       switch (ctgXsltEntityName) 
       { 
        case "Included.xsl": 
         entityXslt = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n <xsl:template name=\"Included\">\n\n </xsl:template>\n</xsl:stylesheet>"; 
         break; 
       } 

       UTF8Encoding utf8Encoding = new UTF8Encoding(); 
       byte[] entityBytes = utf8Encoding.GetBytes(entityXslt); 
       entityStream = new MemoryStream(entityBytes); 

       break; 
     } 

     return entityStream; 
    } 

    public override Uri ResolveUri(Uri baseUri, string relativeUri) 
    { 
     // You might want to resolve all reference URIs using a custom scheme. 
     if (baseUri != null) 
      return base.ResolveUri(baseUri, relativeUri); 
     else 
      return new Uri("custom-scheme:" + relativeUri); 
    } 
} 

आप मुख्य लोड करते हैं।XSL दस्तावेज़ आप निम्नलिखित के लिए प्रासंगिक कोड को बदल देंगे:

xslt.Load(xpDoc, new XsltSettings(true, true), new CustomXmlResolver()); 

ऊपर के उदाहरण की जानकारी मैं उठाया-अप MSDN लेख Resolving the Unknown: Building Custom XmlResolvers in the .NET Framework में पर आधारित था।

0

मैं पहले से ही स्मृति में सभी का उपयोग कर परिवर्तनों कर के साथ सफलता है:

रखना एक xslt निम्नलिखित युक्त शामिल हैं:

आयात href = "Common.xslt" और आयात href = "Xhtml.xslt"

private string Transform(string styleSheet, string xmlToParse) 
      { 
       XslCompiledTransform xslt = new XslCompiledTransform(); 

       MemoryResourceResolver resolver = new MemoryResourceResolver();    


       XmlTextReader xR = new XmlTextReader(new StringReader(styleSheet));   

       xslt.Load(xR, null, resolver); 

       StringWriter sw = new StringWriter();     


       using (var inputReader = new StringReader(xmlToParse)) 
       { 
        var input = new XmlTextReader(inputReader); 
        xslt.Transform(input, 
             null, 
             sw); 
       } 

       return sw.ToString(); 

      }  

    public class MemoryResourceResolver : XmlResolver 
     { 

      public override object GetEntity(Uri absoluteUri, 
       string role, Type ofObjectToReturn) 
      { 
       if (absoluteUri.ToString().Contains("Common")) 
       { 
        return new MemoryStream(Encoding.UTF8.GetBytes("Xml with with common data")); 
       } 

       if (absoluteUri.ToString().Contains("Xhtml")) 
       { 
        return new MemoryStream(Encoding.UTF8.GetBytes("Xml with with xhtml data")); 
       }   

       return ""; 
      } 
     } 

ध्यान दें कि पूरी तरह से सभी सामग्री को तार प्रकार है: स्टाइल शीट, xmlToParse और "आम" और "Xhtml" आयात की सामग्री

संबंधित मुद्दे