为何FOP 2.7中URI的反斜杠会自动转换为正斜杠?
问题描述
我正尝试通过命令行使用FOP 2.7,将经XSLT(v2.0)样式化的基础XML文件生成PDF文档。输入XML的某个标签属性包含URL,该URL需作为可点击链接放入输出PDF中。
示例XML文件
<?xml version='1.0' ?> <testxmlroot> <name>Test URL</name> <a href ="https://example.com/someting/Default/GetSometing?path=\one\two\three%20four\five"/> <desc>Example of the type of URL required.</desc> </testxmlroot>
示例XSL文件
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:altova="http://www.altova.com" xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="altova"> <xsl:output version="1.0" method="xml" encoding="UTF-8" indent="no"/> <xsl:param name="SV_OutputFormat" select="'PDF'"/> <xsl:variable name="fo:layout-master-set"> <fo:layout-master-set> <fo:simple-page-master master-name="page-master-0-even" margin-left="0.1in" margin-right="0.1in" page-height="8.3in" page-width="11.7in" margin-top="0.1in" margin-bottom="0.30in"> <fo:region-body column-count="1"/> <fo:region-before region-name="even-page-header" overflow="hidden"/> </fo:simple-page-master> <fo:simple-page-master master-name="page-master-0-odd" margin-left="0.1in" margin-right="0.1in" page-height="8.3in" page-width="11.7in" margin-top="0.1in" margin-bottom="0.30in"> <fo:region-body column-count="1"/> <fo:region-before region-name="odd-page-header" overflow="hidden"/> </fo:simple-page-master> <fo:page-sequence-master master-name="page-master-0"> <fo:repeatable-page-master-alternatives> <fo:conditional-page-master-reference master-reference="page-master-0-even" odd-or-even="even"/> <fo:conditional-page-master-reference master-reference="page-master-0-odd" odd-or-even="odd"/> </fo:repeatable-page-master-alternatives> </fo:page-sequence-master> </fo:layout-master-set> </xsl:variable> <xsl:variable name="altova:nPxPerIn" select="96"/> <xsl:template match="/"> <fo:root> <xsl:copy-of select="$fo:layout-master-set"/> <fo:declarations> <x:xmpmeta xmlns:x="adobe:ns:meta/"> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/"> <xmp:CreatorTool>Altova StyleVision Enterprise Edition 2016 (http://www.altova.com)</xmp:CreatorTool> </rdf:Description> </rdf:RDF> </x:xmpmeta> </fo:declarations> <!--PDF Main Heading--> <fo:page-sequence force-page-count="no-force" master-reference="page-master-0" initial-page-number="1" format="1"> MainHeading <fo:flow flow-name="xsl-region-body"> <fo:block> <xsl:for-each select ="//a"> <xsl:if test ="@href"> <fo:basic-link color ="blue" text-decoration ="underline" external-destination =" {@href}"> <xsl:value-of select ="@href" disable-output-escaping ="yes"/> </fo:basic-link> </xsl:if> </xsl:for-each> </fo:block> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> </xsl:stylesheet>
命令行输入
./fop.bat -xml "E:\StackOverflow.xml" -xsl "E:\StackOverflow.xsl" -pdf E:\FOPExperimentation\outputfile.pdf -c E:\fop.xconf
遇到的问题
生成的PDF中,显示的文本保留了XML中的反斜杠,但点击链接或复制URL时,反斜杠被转换为正斜杠,导致该URL无法正常使用。
原因分析
- PDF的链接遵循URI标准(RFC 3986),要求路径分隔符使用正斜杠
/,FOP在处理external-destination属性时,会自动将非标准的反斜杠\转换为符合规范的正斜杠。 - 显示文本是直接输出XML中的原始内容,未经过URI规范转换,因此保留了反斜杠,最终导致显示内容与实际跳转URL不一致。
解决方法
要让显示文本和跳转URL一致且保留反斜杠,需对URL中的反斜杠进行URI编码(转换为%5C),这样FOP不会修改编码后的字符,浏览器点击链接时会自动解码还原为反斜杠。
修改XSL中fo:basic-link的代码:
<fo:basic-link color="blue" text-decoration="underline" external-destination="{replace(@href, '\\', '%5C')}"> <xsl:value-of select="@href"/> </fo:basic-link>
关键说明:
replace(@href, '\\', '%5C'):利用XSLT 2.0的字符串替换函数,将URL中的反斜杠(XML中需用\\表示单个\)替换为URI编码后的%5C。- 移除
disable-output-escaping="yes":无需转义,直接输出原始URL即可,保证显示文本保留反斜杠,同时跳转链接使用编码后的合法URI。
处理后,PDF显示的文本和实际跳转URL都会正确保留反斜杠,确保链接正常使用。
内容的提问来源于stack exchange,提问作者HopefulLearner
相关产品推荐
相关产品推荐

