XSLT:将base64数据转换为图像文件

9

我看到了一些关于如何将图像文件编码为base64的问题,但反过来呢?我该如何从存储在XML文件中的base64字符串重新构建出图片呢?

<resource>
<data encoding="base64">
R0lGODlhEAAQAPMAMcDAwP/crv/erbigfVdLOyslHQAAAAECAwECAwECAwECAwECAwECAwECAwEC
AwECAyH/C01TT0ZGSUNFOS4wGAAAAAxtc09QTVNPRkZJQ0U5LjAHgfNAGQAh/wtNU09GRklDRTku
MBUAAAAJcEhZcwAACxMAAAsTAQCanBgAIf8LTVNPRkZJQ0U5LjATAAAAB3RJTUUH1AkWBTYSQXe8
fQAh+QQBAAAAACwAAAAAEAAQAAADSQhgpv7OlDGYstCIMqsZAXYJJEdRQRWRrHk2I9t28CLfX63d
ZEXovJ7htwr6dIQB7/hgJGXMzFApOBYgl6n1il0Mv5xuhBEGJAAAOw==
</data>
<mime>image/gif</mime>
<resource-attributes>
    <file-name>clip_image001.gif</file-name>
</resource-attributes>
</resource>

给定上述XML节点resource,我该如何创建clip_image001.gif
请提供以下建议:
  1. XSLT处理器和/或扩展程序使其成为可能,加上
  2. 触发转换的示例XSLT
请注意,它必须能够处理至少GIF和PNG文件格式。最好不受任何操作系统的限制。

已实现的解决方案

基于Mads Hansen的解决方案。主要区别在于,我直接在我的命名空间中引用了net.sf.saxon.value.Base64BinaryValue,而不是使用saxon命名空间,因为我对Java API的理解比Saxonica网站描述的base64Binary-to-octetsbase64Binary函数更直观。

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:b64="net.sf.saxon.value.Base64BinaryValue"
    xmlns:fos="java.io.FileOutputStream"
    ...
    exclude-result-prefixes="b64 fos">
...
<xsl:for-each select="resource">                
    <xsl:variable name="b64" select="b64:new(string(data))"/>
    ...
    <xsl:variable name="fos" select="fos:new(string($img))"/>
    <xsl:value-of select="fos:write($fos, b64:getBinaryValue($b64))"/>  
    <xsl:value-of select="fos:close($fos)"/>
</xsl:for-each>
...

P.S. 请参考同类问题中的实现,以获取识别图像文件所需的哈希值。


本问题是我之前提出的另一个问题的子问题。

4个回答

10

我从XSL邮件列表中找到了这篇文章,它介绍了如何使用Saxon扩展函数xs:base64Binary-to-octet在XSLT 2.0样式表中使用Java FileOutputStream将其流式输出到文件中:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema";
xmlns:saxon="http://saxon.sf.net/";
xmlns:fos="java.io.FileOutputStream">
<xsl:template match="/">
   <xsl:variable name="img" select="concat('c:\test\jesper', '.jpg')"/>
   <xsl:variable name="fos" select="fos:new(string($img))"/>
   <xsl:value-of select="fos:write($fos,
saxon:base64Binary-to-octets(xs:base64Binary(my-base64-encoded-image)))"/>
   <xsl:value-of select="fos:close($fos)"/>
</xsl:template>
</xsl:stylesheet>

谢谢!这正是我想要的,因为它实际上将图像写入外部文件。 - bguiz
我认为应该是saxon:base64Binary-to-octets(带有尾随的s)。请参见http://www.saxonica.com/documentation/extensions/functions.html。 - Jukka Matilainen
错误:前缀必须解析为命名空间:xs,在行xs:base64Binary(my-base64-encoded-image)上,更多扩展函数http://saxon.sf.net/:base64Binary-to-octets未知。 - Sarz
@Sarz 我相信这是高级功能,您需要PE或EE版本。http://www.saxonica.com/html/documentation/functions/saxon/base64Binary-to-octets.html - Mads Hansen

7
以下内容可行:
<img>
  <xsl:attribute name="src">
    <xsl:value-of select="concat('data:image/gif;base64,',xPath)"/>
  </xsl:attribute>
</img>

+1 @StrangeDays:感谢您的回答!我不会很快去研究这个(已经是很久以前的事情),但如果它确实有效,那么它看起来比目前在这里提出的其他解决方案更加整洁和优雅。 - bguiz
忘记在那里加一个空格了: <xsl:value-of select="concat('data:image/gif;base64,', xPath)"/> - Steven
这是生成带有BASE64源的HTML IMG元素。并不完全是问题的答案。 - Pavel Horal

1

将其转换为HTML。

<img src="data:{mime};base64,{data}" />

你使用哪个XSLT处理器和扩展? - bguiz
我希望能够实际生成图像文件,即创建clip_image001.gif,然后在输出的HTML中获取<img src="clip_image001.gif" />,因为我还需要从图片文件生成哈希。 - bguiz

0

自从Saxon 9.5以来,通过EXPath文件扩展模块(在Saxon-PE和Saxon-EE中可用),有一种更好的方法可用。

这是我正在使用的代码片段,用于从Word文档中提取二进制图像文件(源XML格式为WordProcessingML):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:file="http://expath.org/ns/file" xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">

<xsl:template match="/pkg:package">
    <xsl:apply-templates select="pkg:part/pkg:binaryData"/>
</xsl:template>

<xsl:template match="pkg:binaryData">
    <xsl:variable name="filename">
        <xsl:value-of select="replace(../@pkg:name, '/word/media/', '')"/>
    </xsl:variable>
    <xsl:variable name="path" select="concat('/some/folder/', $filename)"/>
    <xsl:message><xsl:value-of select="$path"/></xsl:message>

    <xsl:value-of select="file:write-binary($path, xs:base64Binary(string()))"/>       
</xsl:template>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接