Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

c# - Load xml and xslt from embedded resource in Saxon 9.4he

I am using Saxon 9.4 home edition (Saxon-HE 9.4 .NET) to get support for XSLT 2.0 and XPath 2.0, and XQuery 1.0 in .NET. My code crashes when I load files without an URI.

  1. Is it possible to load xml/xsl documents without an URI related to the document loaded?
  2. If not, is there any way to define URI for elements embedded in dll-files?

Any other solutions will also be appreciated, my only term is that the files must be loaded from within the dll-file.

My code works perfectly as long as i load xml/xsl from file:

const string sourcePath = @"C:estTestInvoiceWithError.xml";
const string xsltpath = @"C:estUBL-T10-BiiRules.xsl";

When i try to load from embedded resource the code throws an exception stating 'No base URI supplied':

Stream sourceStream = GetEmbeddedResource("TestProject1.testfiles.TestInvoice.xml");
Stream xsltStream = GetEmbeddedResource("TestProject1.testfiles.UBL-T10-BiiRules.xsl");

I have also created Uri's for resources with relative path which throws the exception 'This operation is not supported for a relative URI.':

Uri sourceUri = new Uri("/TestProject1;component/testfiles/TestInvoice.xml",     UriKind.Relative);
Uri xsltUri = new Uri("/TestProject1;component/testfiles/UBL-T10-BiiRules.xsl.xml", UriKind.Relative);

Here is my code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Saxon.Api;


namespace TestProject1
{
    [TestClass]
    public class XsltTest
    {
        [TestMethod]
        public void SaxonTest()
        {
            Stream sourceStream = GetEmbeddedResource("TestProject1.testfiles.TestInvoice.xml");
            Stream xsltStream = GetEmbeddedResource("TestProject1.testfiles.UBL-T10-BiiRules.xsl");

            Uri sourceUri = new Uri("/TestProject1;component/testfiles/TestInvoice.xml", UriKind.Relative);
            Uri xsltUri = new Uri("/TestProject1;component/testfiles/UBL-T10-BiiRules.xsl.xml", UriKind.Relative);

            const string sourcePath = @"C:estTestInvoiceWithError.xml";
            const string xsltpath = @"C:estUBL-T10-BiiRules.xsl";

            Processor processor = new Processor();
            XdmNode input = processor.NewDocumentBuilder().Build(new Uri(sourcePath));

            XsltTransformer transformer = processor.NewXsltCompiler().Compile(new Uri(xsltpath)).Load();

            transformer.InitialContextNode = input;

            Serializer serializer = new Serializer();
            StringBuilder sb = new StringBuilder();
            TextWriter writer = new StringWriter(sb);
            serializer.SetOutputWriter(writer);

            transformer.Run(serializer);

            XmlDocument xmlDocOut = new XmlDocument();
            xmlDocOut.LoadXml(sb.ToString());
            XmlNodeList failedAsserts = xmlDocOut.SelectNodes("/svrl:schematron-output/svrl:failed-assert",XmlInvoiceNamespaceManager());

            if (failedAsserts == null)
                return;

            foreach (XmlNode failedAssert in failedAsserts)
            {
                if (failedAssert.Attributes == null)
                    continue;

                XmlAttribute typeOfError = failedAssert.Attributes["flag"];

                if (typeOfError.Value.Equals("warning"))
                {/*Log something*/}
                else if (typeOfError.Value.Equals("fatal"))
                {/*Log something*/}
            }
        }

        private XmlNamespaceManager XmlInvoiceNamespaceManager()
        {
            IDictionary<string, string> list = new Dictionary<string, string>
                                                   {
                                                       {"xml", "http://www.w3.org/XML/1998/namespace"},
                                                       {"xsi", "http://www.w3.org/2001/XMLSchema-instance"},
                                                       {"xsd", "http://www.w3.org/2001/XMLSchema"},
                                                       {"udt","urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2"},
                                                       {"qdt","urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2"},
                                                       {"ext","urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"},
                                                       {"ccts", "urn:un:unece:uncefact:documentation:2"},
                                                       {"cbc","urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"},
                                                       {"cac","urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"},
                                                       {"inv", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"},
                                                       {"svrl", "http://purl.oclc.org/dsdl/svrl"}
                                                   };

            XmlNameTable xmlNameTable = new NameTable();

            XmlNamespaceManager xmlInvoiceNamespaceManager = new XmlNamespaceManager(xmlNameTable);

            foreach (KeyValuePair<string, string> ns in list)
            {
                xmlInvoiceNamespaceManager.AddNamespace(ns.Key, ns.Value);
            }
            return xmlInvoiceNamespaceManager;
        }

        protected static Stream GetEmbeddedResource(string path)
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            Stream stream = asm.GetManifestResourceStream(path);
            return stream;
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think you can load from a stream with Saxon but you need to set a base URI first that would allow to load any references resources (like a DTD in an XML document or like included or imported stylesheet modules). If you are sure you don't have that then simply try e.g.

DocumentBuilder db = processor.NewDocumentBuilder();
db.BaseUri = new Uri("file:///C:/");

XdmNode input = db.Build(xsltStream);

Obviously if you need to resolve relative URIs in the XSLT that are also to be loaded as embedded resource more work is needed: you need to set up the XmlResolver to a class that supports loading the resource from an embedded resource, together with a scheme of URIs in the XSLT to indicate to the resolver that you need to load from a resource. I don't think the .NET framework provides such a kind of XmlResolver and the Uri class does not support a custom schema for that either.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...