通过freemarker模板,使用jsoup将html转换为word,包含图片

本文介绍了如何通过Freemarker模板和Jsoup库将HTML内容转换为Word文档。首先,创建XML模板并在Word中填充内容以确定所需格式。接着,利用Jsoup解析HTML,将内容保存到Map中。最后,使用Freemarker模板替换动态数据,并将XML文件转换为docx格式的Word文档。此外,涉及图片处理、表格和文字段落的处理方法,以及需要的工具和包的引用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现思路:

一、制作模板

1、在word中无非三种格式,文字、图片、表格,目前我所涉及到的业务中只有这三个,其他情况没涉及到没研究,首先需要准备一个模板文件,即xml格式的模板,通过打开一个空白的word文档,另存为xml文件,即可得到一个空白的word模板(可使用notepad++工具打开)

2、获取到空白文档的模板后,再新建一个word,填充文字,再另存为xml,打开并对比之前空白的模板之间的差异,可以找出添加文字后加了哪些代码。如果需要表格,则在空白文档加入加入表格,然后保存为xml文件打开查看代码,对比差异,可以知道具体的代码代表的意思。

3、图片方面的处理,同样是在空白文档中添加图片,然后查看xml代码,其中图片是以base64形式出现的,在替换图片的过程中,是需要将图片的base64码进行替换,所有的需要动态改变的数据,都使用freemarker标签的形式替换,如果不了解的,自行去了解一下freemarker标签的使用,具体的在xml中的代码的代表意思,可以到百度查找。

二、填充模板

1、后台使用jsoup解析HTML代码后,获取html代码中的值,保存到map中。文字段落,图片,表格,可分开处理。解析的HTML代码是通过百度UEditor生成的代码,如果是需要解析完整的正规的html代码,需要另外写解析标签的代码。

2、解析HTML时,可对应保存HTML中标签存在的属性,对应xml中的属性,通过实体来进行设置,遍历标签时,获取实体属性即可

3、填充模板保存后的文件仍然是xml格式的文件,需要另外处理,将文件另存为docx格式的word文档

 

实现代码:

注意:代码仅可以作为参考,即使完全复制,也不一定适合你,仅仅提供一个思路和参考,是否值得借鉴,需要自己评估,或者有更好的方法,欢迎留言评论一起交流

模板代码:(xml模板的代码,只贴出body中的代码)

<w:body>
		<wx:sect>
			<!-- 判断第一部分是文字段落,并遍历第一部分的段落 -->
			<#if part1 == "paragraph">
			<#list paragraphList1 as paragraph>
			<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
				<w:pPr>
					<w:jc w:val="${paragraph.align}"/>
					<w:rPr>
						<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
						<wx:font wx:val="宋体"/>
						<w:color w:val="${paragraph.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
					</w:rPr>
					<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
				</w:pPr>
				<!-- 遍历段落中的wr,每个wr可定义对应的文字属性,如果内容不为空,则执行文字遍历循环 -->
				<#list paragraph.wrList as wr>
				<#if wr.content??>
				<w:r>
					<w:rPr>
						<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
						<wx:font wx:val="${wr.font}"/>
						<w:color w:val="${wr.color}"/>
						<#if paragraph_index==0>
						<w:sz w:val="30"/>
						<w:sz-cs w:val="30"/>
						<#else>
						<w:sz w:val="${paragraph.size}"/>
						<w:sz-cs w:val="${paragraph.size}"/>
						</#if>
						${wr.bold}
						${wr.tilt}
						${wr.underLine}
					</w:rPr>
					<w:t>${wr.content}</w:t>
				</w:r>
				</#if>
				<!-- 如果是图片,则在wr上添加图片 -->
				<#if wr.hasImg == 1>
				<#list wr.imgList as image>
				<w:r wsp:rsidRPr="006E22D7">
					<w:rPr>
						<w:noProof/>
					</w:rPr>
					<w:pict>
						<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
							<v:stroke joinstyle="miter"/>
							<v:formulas>
								<v:f eqn="if lineDrawn pixelLineWidth 0"/>
								<v:f eqn="sum @0 1 0"/>
								<v:f eqn="sum 0 0 @1"/>
								<v:f eqn="prod @2 1 2"/>
								<v:f eqn="prod @3 21600 pixelWidth"/>
								<v:f eqn="prod @3 21600 pixelHeight"/>
								<v:f eqn="sum @0 0 1"/>
								<v:f eqn="prod @6 1 2"/>
								<v:f eqn="prod @7 21600 pixelWidth"/>
								<v:f eqn="sum @8 21600 0"/>
								<v:f eqn="prod @7 21600 pixelHeight"/>
								<v:f eqn="sum @10 21600 0"/>
							</v:formulas>
							<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
							<o:lock v:ext="edit" aspectratio="t"/>
						</v:shapetype>
						<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
						<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
							<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
						</v:shape>
					</w:pict>
				</w:r>
				</#list>
				</#if>
				</#list>
			</w:p>
			</#list>
			</#if>
			<!-- 如果第一部分是表格,则填充表格 -->
			<#if part1 == "table">
			<w:tbl>
				<w:tblPr>
					<w:tblW w:w="8522" w:type="dxa"/>
					<w:tblBorders>
						<w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
						<w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
					</w:tblBorders>
					<!-- 设置表格的对齐方式 -->
					<w:tblLook w:val="${table.tblLook}"/>
				</w:tblPr>
				<w:tblGrid>
					<!-- 表格列,定义的表格有多少列,则遍历显示多少个网格 -->
					<#list table.gridColList as gridCol>
					${gridCol}
					</#list>
				</w:tblGrid>
				<!-- 遍历表格中的行,tr -->
				<#list table.trList as tr>
				<w:tr wsp:rsidR="00616293" wsp:rsidRPr="00616293" wsp:rsidTr="00616293">
					<w:trPr>
						<!-- 设置行高属性 -->
						<w:trHeight w:val="${tr.height}"/>
					</w:trPr>
					<!-- 遍历行中的列 -->
					<#list tr.tdList as td>
					<w:tc>
						<w:tcPr>
							<!-- 列宽属性 -->
							<w:tcW w:w="${td.width}" w:type="dxa"/>
							<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
							<w:tcBorders>
								${td.top}
								${td.right}
								${td.bottom}
								${td.left}
							</w:tcBorders>
							${td.gridSpan}
							${td.merge}
						</w:tcPr>
						<!-- 遍历单元格中的段落文字 -->
						<#list td.paragraphList as paragraph>
						<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
							<w:pPr>
								<!-- 设置单元格中段落的属性 -->
								<w:jc w:val="${paragraph.align}"/>
								<w:rPr>
									<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
									<wx:font wx:val="宋体"/>
									<w:color w:val="${paragraph.color}"/>
									<#if tr_index==0>
									<w:sz w:val="30"/>
									<w:sz-cs w:val="30"/>
									<#else>
									<w:sz w:val="${paragraph.size}"/>
									<w:sz-cs w:val="${paragraph.size}"/>
									</#if>
								</w:rPr>
								<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
							</w:pPr>
							<!-- 遍历段落中的wr -->
							<#list paragraph.wrList as wr>
							<!-- 如果内容不为空,则执行文字遍历循环 -->
							<#if wr.content??>
							<w:r>
								<w:rPr>
									<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
									<wx:font wx:val="${wr.font}"/>
									<w:color w:val="${wr.color}"/>
									<#if tr_index==0>
									<w:sz w:val="30"/>
									<w:sz-cs w:val="30"/>
									<#else>
									<w:sz w:val="${paragraph.size}"/>
									<w:sz-cs w:val="${paragraph.size}"/>
									</#if>
									${wr.bold}
									${wr.tilt}
									${wr.underLine}
								</w:rPr>
								<w:t>${wr.content}</w:t>
							</w:r>
							</#if>
							<!-- 如果是图片,则在wr上添加图片 -->
							<#if wr.hasImg == 1>
							<!-- 遍历图片 -->
							<#list wr.imgList as image>
							<w:r wsp:rsidRPr="006E22D7">
								<w:rPr>
									<w:noProof/>
								</w:rPr>
								<w:pict>
									<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
										<v:stroke joinstyle="miter"/>
										<v:formulas>
											<v:f eqn="if lineDrawn pixelLineWidth 0"/>
											<v:f eqn="sum @0 1 0"/>
											<v:f eqn="sum 0 0 @1"/>
											<v:f eqn="prod @2 1 2"/>
											<v:f eqn="prod @3 21600 pixelWidth"/>
											<v:f eqn="prod @3 21600 pixelHeight"/>
											<v:f eqn="sum @0 0 1"/>
											<v:f eqn="prod @6 1 2"/>
											<v:f eqn="prod @7 21600 pixelWidth"/>
											<v:f eqn="sum @8 21600 0"/>
											<v:f eqn="prod @7 21600 pixelHei
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值