recherche

Maison  >  Questions et réponses  >  le corps du texte

XSLT - Convertir des images (et pdf) en base64

J'ai utilisé Apache FOP 2.8 pour convertir des fichiers au format intermédiaire (IF) Apache FOP en HTML 文件 avec une feuille de style xslt auto-écrite.

En tant que bibliothèque externe, je n'ai actuellement installé que saxon12he.

Problème n°1 (Image en base64)

Dans le document source IF, il y a un élément image xml comme celui-ci :

<image xlink:href="files\Logo.png"/>

Il serait facile de le convertir en HTML et d'obtenir un résultat similaire

<img src="files\Logo.png"/>

Lorsque vous utilisez le modèle suivant :

<xsl:template match="image">
    <xsl:variable name="file-path"><xsl:value-of select="@xlink:href"/></xsl:variable>
    <img src="{$file-path}"/>
</xsl:template>

La question ici est générée HTML-file 不能是“独立的”...意味着除了 HTML-file 之外还必须有 < code>files 目录,其中包含 Logo.png,以便 HTML-file 找到图像路径 filesLogo.png< /p>

Mais ce que je veux réaliser, c'est HTML 文件être "indépendant".

Existe-t-il un moyen de convertir Logo.png 转换为 Base64, peut-être via un simple appel de fonction comme :

<xsl:template match="image">
    <xsl:variable name="file-path"><xsl:value-of select="@xlink:href"/></xsl:variable>
    <img src="to-base64($file-path)"/>
</xsl:template>

Créez la sortie suivante :

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...."/>

Question n°2 (pdf en base64)

L'autre partie délicate est que, dans le format intermédiaire, xlink:href 也可以生成 .pdf les fichiers...

<image xlink:href="files\Table_1234.pdf"/>

Ce serait formidable si vous pouviez la convertir en image Base64 de la même manière que ci-dessus.

Ou peut-être existe-t-il une autre façon de rendre le document HTML "autonome", mais la conversion en base64 est la seule idée que j'ai jusqu'à présent.

Méthode 1 (fonction d'extension Java saxonne)

J'ai essayé de créer une fonction d'extension Java pour Saxon 12 HE en suivant ce document

J'en ai donc implémenté unExtensionFunctionDefinition

import net.sf.saxon.expr.XPathContext;
import net.sf.saxon.lib.ExtensionFunctionCall;
import net.sf.saxon.lib.ExtensionFunctionDefinition;
import net.sf.saxon.om.Sequence;
import net.sf.saxon.om.StructuredQName;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.value.SequenceType;
import net.sf.saxon.value.StringValue;

public class ImageToBase64 extends ExtensionFunctionDefinition {
    @Override
    public StructuredQName getFunctionQName() {
        return new StructuredQName("ext", "http://example.com/saxon-extension", "imageToBase64");
    }

    @Override
    public SequenceType[] getArgumentTypes() {
        return new SequenceType[]{SequenceType.SINGLE_STRING};
    }

    @Override
    public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
        return SequenceType.SINGLE_STRING;
    }

    @Override
    public ExtensionFunctionCall makeCallExpression() {
        return new ExtensionFunctionCall() {
            @Override
            public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
                var filePath = ((StringValue)arguments[0]).getStringValue();
                // open file and convert to base64 string
                var resultBase64 = "12345";
                return StringValue.makeStringValue(resultBase64);
            }
        };
    }
}

Parce que la documentation dit : "Les classes implémentant ces fonctions étendues doivent être enregistrées dans la configuration " Cela peut être fait "en sous-classant net.sf.saxon.Transform ou net.sf.saxon.Query, en remplaçant la méthode applyLocalOptions( ) afin qu'il fasse l'appel approprié à config.registerExtensionFunction(); " J'ai également ajouté une extension net.sf.saxon.Transform < /代码> :

import net.sf.saxon.Transform;
import net.sf.saxon.trans.CommandLineOptions;

public class Configuration extends Transform {
    @Override
    protected void applyLocalOptions(CommandLineOptions options, net.sf.saxon.Configuration config) {
        config.registerExtensionFunction(new ImageToBase64());
        super.applyLocalOptions(options, config);
    }
}

Quand je construis l'artefact pour obtenir jar 文件时(我使用 IntelliJ d'ailleurs. ) J'ai seulement ajouté "sortie de compilation", donc le pot a fini par faire 3 Ko .

Ensuite, j'ai mis le pot dans le dossier lib à côté d'Apache FOP saxon-he-12.2.jar et j'ai ajouté xmlns:ext="http://example.com/saxon-extension"xsl:stylesheet.

Mais quand j'appelle maintenant

<xsl:value-of select="ext:imageToBase64('my/file/path')"/>

J'ai eu une erreurnet.sf.saxon.trans.XPathException:找不到名为 Q{http://example.com/saxon-extension}imageToBase64() 的 1 参数函数< /p>

P粉529245050P粉529245050377 Il y a quelques jours560

répondre à tous(1)je répondrai

  • P粉128563140

    P粉1285631402024-01-17 09:10:25

    Je l'ai fait avec l'aide de @MartinHonnen qui m'a dit de créer ma propre fonction d'extension.

    J'ai donc créé un nouveau programme java (important pour utiliser Java 8) et ajouté deux classes :

    package ExtensionsPackage;
    
    import net.sf.saxon.expr.XPathContext;
    import net.sf.saxon.lib.ExtensionFunctionCall;
    import net.sf.saxon.lib.ExtensionFunctionDefinition;
    import net.sf.saxon.om.Sequence;
    import net.sf.saxon.om.StructuredQName;
    import net.sf.saxon.trans.XPathException;
    import net.sf.saxon.value.SequenceType;
    import net.sf.saxon.value.StringValue;
    
    public class ImageToBase64 extends ExtensionFunctionDefinition {
        @Override
        public StructuredQName getFunctionQName() {
            return new StructuredQName("ext", "http://example.com/saxon-extension", "imageToBase64");
        }
    
        @Override
        public SequenceType[] getArgumentTypes() {
            return new SequenceType[]{SequenceType.SINGLE_STRING};
        }
    
        @Override
        public SequenceType getResultType(SequenceType[] suppliedArgumentTypes) {
            return SequenceType.SINGLE_STRING;
        }
    
        @Override
        public ExtensionFunctionCall makeCallExpression() {
            return new ExtensionFunctionCall() {
                @Override
                public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
                    String filePath = ((StringValue)arguments[0]).getStringValue();
                    // open file and convert to base64 string
                    String resultBase64 = "12345";
                    return StringValue.makeStringValue(resultBase64);
                }
            };
        }
    }
    

    Et sur cette base stackoverflow-entry une autre classe MyTransformerFactory :

    package ExtensionsPackage;
    
    import net.sf.saxon.Configuration;
    import net.sf.saxon.TransformerFactoryImpl;
    import net.sf.saxon.lib.ExtensionFunctionDefinition;
    
    public class MyTransformerFactory extends TransformerFactoryImpl {
        public MyTransformerFactory() {
            super();
            ExtensionFunctionDefinition imageToBase64Function = new ImageToBase64();
            this.getProcessor().registerExtensionFunction(imageToBase64Function);
        }
    
        public MyTransformerFactory(Configuration config) {
            super(config);
            ExtensionFunctionDefinition imageToBase64Function = new ImageToBase64();
            this.getProcessor().registerExtensionFunction(imageToBase64Function);
        }
    }
    

    Maintenant, créez un dossier jar 文件并将其放入 Apache FOP 的 lib.

    Puis ajoutez set CUSTOMOPTS=-Djavax.xml.transform.TransformerFactory=ExtensionsPackage.MyTransformerFactory À fop.bat 并将 %CUSTOMOPTS% 添加到 :runFop.

    Ajouter un espace de noms à la feuille de style :

    <xsl:stylesheet version="1.0" 
        xmlns:ext="http://example.com/saxon-extension">
    

    et utilisez-le comme ceci :

    <xsl:value-of select="ext:imageToBase64('my/file/path')"/>
    

    Si vous exécutez maintenant fop.bat via la console xsl:value-of 将提供 12345.

    répondre
    0
  • Annulerrépondre