Comment résoudre et des éléments avec des chemins relatifs lors de l'utilisation de xsltc.exe xslcompiledTransformes?

StackOverflow https://stackoverflow.com/questions/8991755

  •  13-11-2019
  •  | 
  •  

Question

Dans le cadre du processus de construction de notre application Web, j'ai configuré nos feuilles de styles XSLT à construire avec Xsltc.exe de Microsoft compilateur chaque fois que nous exécutons une compilation complète. Pendant le développement local, cela a très bien fonctionné, car le code est compilé et hébergé au même endroit. Cependant, une fois que cela a été mis sur le serveur de construction, des problèmes se sont posés.

Le serveur de construction compilera les feuilles de styles XSLT comme je le fais localement, mais un script s'exécute qui déploie le code compilé vers notre serveur Web interne de stadification. Une fois que ces binaires ont déménagé d'où ils ont été compilés, les chemins relatifs <xsl:import> et <xsl:include> Les éléments ne résolvent plus correctement, provoquant des exceptions qui ressemblent à ceci lorsque les feuilles de style XSLT sont exécutées.

Could not find a part of the path 'e:\{PATH}\xslt\docbook\VERSION'.
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at 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, Boolean useLongPath)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy)
    at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize)
    at System.Xml.XmlUrlResolver.GetEntity(Uri absoluteUri, String role, Type ofObjectToReturn)
    at System.Xml.Xsl.Runtime.XmlQueryContext.GetDataSource(String uriRelative, String uriBase)

Voici une idée générale du code tel qu'il est maintenant:

var xslt = new XslCompiledTransform();
xslt.Load(typeof(Namespace.XslTransforms.CompiledXsltStylesheet));
xslt.Transform("input.xml", "output.xml");

À l'heure actuelle, j'utilise la méthode xslcompiledTransform.load () avec un seul paramètre «type» pour apporter les feuilles de styles XSLT pré-compilées basées sur XSLTC.EXE. Je peux dire à partir de la trace de pile que le Framework .NET utilise le XMlurlResolver pour essayer de résoudre l'emplacement réel de ces feuilles de style externe, mais je ne vois pas de moyen de fournir une implémentation remplacée de XMLResolver où je pourrais passer dans un nouveau BUSURI qui pointe où ces feuilles de style vivent sur le serveur Web.

Je suppose que je peux résoudre ce problème en ne pré-compilant plus avec xsltc.exe et en chargeant les feuilles de styles XSLT via XMLReaders, car cela me permettra d'utiliser le autres méthodes xslcompiledTransform.load () qui ont un paramètre où je pourrais fournir ma propre implémentation XMLResolver. Cependant, j'aime l'option de pré-compilation pour la validation et les performances de la syntaxe, donc je ne veux pas l'abandonner, sauf si je le dois absolument.

Existe-t-il un moyen d'utiliser xsltc.exe pour pré-compiler ces feuilles de styles XSLT, tout en fournissant un moyen d'indiquer explicitement la fondation pour une résolution de chemin relative de <xsl:include> et <xsl:import> Éléments lors de l'exécution?

Était-ce utile?

La solution

Après un parcelle de jouer avec cela, j'ai découvert que j'avais raison que le code que j'ai fourni utilise automatiquement le System.xml.xmlurlresolver Pour résoudre le <xsl:include> et <xsl:import> Chemins relatifs au moment de l'exécution. Cependant, l'utilisation du XMlurlresolver n'est pas liée au System.xml.xslcompiledTransform Quand il est placé dans un binaire par xsltc.exe. Le XMLResolver est en fait choisi par le Xmlresolver propriété sur le System.xml.xmlreadersettings sur le System.xml.xmlreader Cela effectue la transformation au moment de l'exécution. Une fois que j'ai réglé mon propre XMLResolver personnalisé sur les XSLTreadersettings que j'utilisais, j'ai pu contrôler la résolution de chemin relative.

Si vous souhaitez remplacer ce XMLResolver comme je l'ai fait, le code suivant peut être utilisé comme guide:

var customXmlResolver = new SomeCustomXmlResolver();  // Derives from XmlResolver
var xmlReaderSettings = new XmlReaderSettings {
  XmlResolver = customXmlResolver
};

var xslt = new XslCompiledTransform();
xslt.Load(typeof(Namespace.XslTransforms.CompiledXsltStylesheet));

using (var xmlReader = XmlReader.Create("input.xml", xmlReaderSettings)) {
  using (var xmlWriter = XmlWriter.Create("output.xml")) {
    xslt.Transform(xmlReader, null, xmlWriter, customXmlResolver);
  }
}

J'utilise toujours xsltc.exe Pour compiler mes feuilles de styles XSLT, mais lorsque je charge ces feuilles de style compilées sur le serveur Web, l'injecté SomeCustomXmlResolver réécrit les chemins de remplacement ResolveUri() et GetEntity() méthodes afin que les fichiers référencés qui vivent dans le <xsl:include> et <xsl:import>-Les chemins relatifs basés sur se trouvent. En bonus supplémentaire, en ajoutant le même XMLResolver à la fin du Transform() méthode, document() Les opérations dans le XML verront également leurs chemins relatifs résolus correctement.

Autres conseils

Existe-t-il un moyen d'utiliser xsltc.exe pour pré-compiler ces feuilles de styles XSLT, tout en fournissant un moyen d'indiquer explicitement la fondation pour une résolution de chemin relative de <xsl:include> et <xsl:import> Éléments lors de l'exécution?

Essayez d'utiliser:

XslcompiledTransform.CompileTotype ()

L'un des arguments que cette méthode statique accepte est:

XmlResolver stylesheetResolver

Je ne sais pas si cela casse votre système, mais que diriez-vous au lieu de

  1. compilation avec xsltc.exe
  2. déploiement du binaire
  3. Chargement du binaire avec cette Load()

tu

  1. déployer les feuilles de style, mais beaucoup sont nécessaires import/include directives
  2. Chargez la feuille de style principale avec cette Load(), spécifiant le résolveur pour le import/incldue

Il semble que vous bénéficierez toujours d'une feuille de style "compilée", au moins en temps d'exécution.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top