XSL-FO合并不同节点两行内容求助:XML与FOP技术问题咨询
解决XSL-FO合并XML不同节点内容的问题
嘿,我来帮你搞定XSL-FO合并XML节点内容的问题!从你给出的XML片段来看,你有多个<PartDtl>节点,想要把不同节点里的内容合并成一行对吧?下面我给你两种常见场景的实用解决方案,你可以根据实际需求调整:
场景1:按相同属性分组合并(比如同RepTyp的节点)
如果你的需求是把所有RepTyp相同的<PartDtl>内容合并成一行,用XSLT的分组功能就能轻松实现。这里用<xsl:key>来分组,再在XSL-FO里输出合并后的内容:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml" indent="yes"/> <!-- 定义分组规则:按RepTyp字段分组 --> <xsl:key name="partByRepTyp" match="PartDtl" use="RepTyp"/> <xsl:template match="/selectedcalculation/CLASSXml/CalcData/SpareParts"> <fo:root> <!-- 定义页面布局 --> <fo:layout-master-set> <fo:simple-page-master master-name="page" page-width="210mm" page-height="297mm"> <fo:region-body margin="20mm"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="page"> <fo:flow flow-name="xsl-region-body"> <!-- 遍历每个唯一的RepTyp分组 --> <xsl:for-each select="PartDtls/PartDtl[generate-id() = generate-id(key('partByRepTyp', RepTyp)[1])]"> <fo:block font-size="14pt" font-weight="bold" margin-bottom="5mm"> 维修类型: <xsl:value-of select="RepTyp"/> </fo:block> <!-- 合并输出该分组下的所有零件信息 --> <fo:block margin-bottom="10mm" font-size="12pt"> <xsl:for-each select="key('partByRepTyp', RepTyp)"> <!-- 给除第一个外的内容加分隔符 --> <xsl:if test="position() > 1"> | </xsl:if> <xsl:value-of select="PartDesc"/> (<xsl:value-of select="PartNo"/>) - <xsl:value-of select="Price"/> </xsl:for-each> </fo:block> </xsl:for-each> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> </xsl:stylesheet>
这段代码会把所有RepTyp为E的零件信息合并成一行,用|分隔,排版成清晰的块级内容。
场景2:合并指定节点的内容(比如特定GId的节点)
如果你的需求是合并特定几个节点(比如GId为0281和0471的零件),可以直接通过变量定位节点,再把它们的字段拼接起来,甚至可以做数值计算:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/selectedcalculation/CLASSXml/CalcData/SpareParts"> <fo:root> <fo:layout-master-set> <fo:simple-page-master master-name="page" page-width="210mm" page-height="297mm"> <fo:region-body margin="20mm"/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="page"> <fo:flow flow-name="xsl-region-body"> <!-- 定位要合并的两个节点 --> <xsl:variable name="frontBumper" select="PartDtls/PartDtl[GId='0281']"/> <xsl:variable name="otherPart" select="PartDtls/PartDtl[GId='0471']"/> <!-- 合并输出内容,还可以计算总价 --> <fo:block font-size="12pt" line-height="1.5"> 合并零件: <xsl:value-of select="$frontBumper/PartDesc"/> + <xsl:value-of select="$otherPart/PartDesc"/> <fo:block>零件编号: <xsl:value-of select="$frontBumper/PartNo"/> & <xsl:value-of select="$otherPart/PartNo"/></fo:block> <fo:block font-weight="bold"> 总价: <xsl:value-of select="number(substring($frontBumper/Price,2)) + number(substring($otherPart/Price,2))"/> HRK </fo:block> </fo:block> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> </xsl:stylesheet>
这里通过substring去掉Price里的+号,转成数值后计算总价,非常实用。
额外提示
如果你的合并规则是其他情况(比如按零件编号前缀、相邻节点合并),只需要调整XSLT里的选择器或分组逻辑就行。另外,XSL-FO部分可以根据你的排版需求,调整字体、间距、表格布局等样式。
内容的提问来源于stack exchange,提问作者Zoran Maćešić
相关产品推荐
相关产品推荐

