XSLT - Convertir des images (et pdf) en base64
P粉529245050
P粉529245050 2024-01-16 16:01:19
0
1
515

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粉529245050
P粉529245050

répondre à tous(1)
P粉128563140

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.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal