【问题标题】:How to add spaces between xml elements xslt transformation如何在xml元素xslt转换之间添加空格
【发布时间】:2016-12-23 17:23:56
【问题描述】:

我有一个如下所示的 XML,我正在使用 XSL FO XSLT 转换生成 PDF。如何在 XML 元素之间添加空格,同时将它们作为 PDF 中的表格列显示?

<Reports>
<Report>
<BatchDate>2016-08-10T00:00:00</BatchDate>
<ClientAccountNo>ABCDE01384</ClientAccountNo>
<Source>N</Source>
<CDSNo>0000001387</CDSNo>
<Price>0.123000</Price>
<Qty>-1200</Qty>
<TCurrency>USD</TCurrency>
<TNettAmt>0</TNettAmt>
<LCurrency>USD</LCurrency>
<LNettAmt>-86.600000</LNettAmt>
<PromotionInd>N</PromotionInd>
<BrkChgID>BRK-N</BrkChgID>
<BrkChgAmt>50.000000</BrkChgAmt>
<ClrChgID>CLR</ClrChgID>
<ClrChgAmt>10.000000</ClrChgAmt>
<SdcChgID>SDC</SdcChgID>
<SdcChgAmt>1.000000</SdcChgAmt>
<BinChgID />
<BinChgAmt>0</BinChgAmt>
<OthChgAmt>0.000000</OthChgAmt>
<TaxAmt>0.000000</TaxAmt>
</Report>
</Reports>

在输出上述 XML 时,我需要在 XML 元素之间添加一个空格,例如,让我们以 TaxAmt 为例,我需要将其输出为 Tax Amt。我怎样才能做到这一点?下面是我的 XSLT

    <fo:table role="html:table" table-layout="auto" inline-progression-dimension="auto" line-height="2.5" width="100%" border="0px" border-collapse="collapse" border-spacing="3px" border-style="outset hidden" space-before.conditionality="retain" space-after.conditionality="retain" space-after="1em" space-before="1em">
          <!--table header-->
          <xsl:for-each select="//Reports/Report[1]/*">
            <fo:table-column column-width="proportional-column-width(4.77)" font-family="sans-serif" font-size="medium" />
          </xsl:for-each>
          <fo:table-header>

            <fo:table-row height="auto" color="#FFFFFF" background-color="#A1A1A1" text-align="center" font-weight="bold" font-family="sans-serif" font-size="medium">
              <xsl:for-each select="/Reports/Report[1]/*">
                <fo:table-cell text-align="center">
                  <fo:block font-size="medium" font-family="sans-serif">
                    <xsl:value-of select="name()"/>
                  </fo:block>
                </fo:table-cell>
              </xsl:for-each>
            </fo:table-row>
          </fo:table-header>
          <!--table body-->
          <fo:table-body>
            <xsl:for-each select="/Reports/Report">
              <fo:table-row display-align="before">
                <xsl:for-each select="*">
                  <fo:table-cell text-align="center" border-top-color="rgb(255, 255, 255)" border-top-style="solid" border-width="1pt" padding="2pt">
                    <fo:block font-size="medium" font-family="sans-serif">
                      <xsl:text>  </xsl:text> <xsl:value-of select="."/>
                    </fo:block>
                  </fo:table-cell>
                </xsl:for-each>
              </fo:table-row>
            </xsl:for-each>
          </fo:table-body>
        </fo:table>

【问题讨论】:

  • 只是为了澄清-您的意思是在元素名称中的所有大写字母之前添加一个空格?如果这就是你要问的,你可以说得更清楚一点。
  • 我需要使所有 XML 元素在呈现到报表时都易于理解。目前我所有的 XML 元素都是数据库列。例如,最终用户不会理解在我的情况下应该是交易货币的元素 TCurrency。

标签: xml xslt-1.0 xsl-fo


【解决方案1】:

以下模板调用在大写字符前插入空格。 XSL 格式化引擎将忽略第一次出现的空格。

<!--xsl:value-of select="name()"/-->
<xsl:call-template name="insertSpaceBeforeUCase">
    <xsl:with-param name="prmStr" select="name()"/>
</xsl:call-template>

...
<xsl:template name="insertSpaceBeforeUCase">
    <xsl:param name="prmStr" select="''"/>
    <xsl:variable name="firstChar" select="substring($prmStr,1,1)"/>
    <xsl:if test="translate($firstChar,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','')=''">
        <xsl:text>&#x20;</xsl:text>
    </xsl:if>
    <xsl:value-of select="$firstChar"/>
    <xsl:if test="string-length($prmStr) &gt; 1">
        <xsl:call-template name="insertSpaceBeforeUCase">
            <xsl:with-param name="prmStr" select="substring($prmStr,2)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

通过此模板调用“TaxAmt”转换为“Tax Amt”。但是“ClrChgID”被转换为“Sdc Chg I D”。后者可能不是你想要的。

XSLT 1.0 对字符串处理有限制。如果您可以将样式表移至 XSLT 2.0,则此问题还有另一种解决方案。

[附录]

比特精炼版来了:

<xsl:template name="insertSpaceBeforeUCase">
    <xsl:param name="prmStr" select="''"/>
    <xsl:param name="prmPrevChar" select="''"/>
    <xsl:variable name="firstChar" select="substring($prmStr,1,1)"/>
    <xsl:variable name="nextChar" select="substring($prmStr,2,1)"/>
    <xsl:if test="(translate($firstChar,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','') = '')
        and ($prmPrevChar != '')
        and ((translate($prmPrevChar,'abcdefghijklmnopqrstuvwxyz','') = '') or ($nextChar != '') and (translate($nextChar,'abcdefghijklmnopqrstuvwxyz','') = ''))">
        <xsl:text>&#x20;</xsl:text>
    </xsl:if>
    <xsl:value-of select="$firstChar"/>
    <xsl:if test="string-length($prmStr) &gt; 1">
        <xsl:call-template name="insertSpaceBeforeUCase">
            <xsl:with-param name="prmStr" select="substring($prmStr,2)"/>
            <xsl:with-param name="prmPrevChar" select="$firstChar"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

此模板生成以下 XSL-FO:

  <fo:table-row height="auto" color="#FFFFFF" background-color="#A1A1A1" text-align="center" font-weight="bold" font-family="sans-serif" font-size="medium">
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Batch Date</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Client Account No</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Source</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">CDS No</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Price</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Qty</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">T Currency</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">T Nett Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">L Currency</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">L Nett Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Promotion Ind</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Brk Chg ID</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Brk Chg Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Clr Chg ID</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Clr Chg Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Sdc Chg ID</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Sdc Chg Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Bin Chg ID</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Bin Chg Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Oth Chg Amt</fo:block>
     </fo:table-cell>
     <fo:table-cell text-align="center">
        <fo:block font-size="medium" font-family="sans-serif">Tax Amt</fo:block>
     </fo:table-cell>
  </fo:table-row>

【讨论】:

  • 感谢您的帮助.. 明白了!
  • 请看这个问题。 link
  • 如何在我的 XSLT 中应用上述模板?你能告诉我如何使用这个我的 XSLT