使用xslt转换xml

时间:2011-05-20 12:55:01

标签: xml xslt xsl-fo

我有以下xml:

<fo:block font-weight="bold" font-style="italic">Some Text Here</fo:block>

我需要使用xsl:

将其转换为以下内容
{\b\iSome Text Here\i0\b0\par}

到目前为止,我设法使用:

选择块元素
<xsl:template match="fo:block">
<xsl:text>{</xsl:text>
    <xsl:apply-templates />
<xsl:text>\par}</xsl:text></xsl:template>

我正在输出:{Some Text Here\par}

我正在努力使用xsl并使用xsl插入属性,有人能给我一个选择这些属性并获得所需结果的示例吗?

3 个答案:

答案 0 :(得分:3)

使用模板模式和<xsl:sort>指令有一种相当简单的方法。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="fo:block">
  <xsl:text>{</xsl:text>
  <xsl:apply-templates select="@*" mode="prefix" />
  <xsl:apply-templates select="node()" />
  <xsl:apply-templates select="@*" mode="suffix">
    <xsl:sort order="descending"/>
  </xsl:apply-templates>
  <xsl:text>\par}</xsl:text>
</xsl:template>

<xsl:template match="@font-weight['bold']" mode="prefix">\b</xsl:template>
<xsl:template match="@font-style['italic']" mode="prefix">\i</xsl:template>

<xsl:template match="@font-weight['bold']" mode="suffix">\b0</xsl:template>
<xsl:template match="@font-style['italic']" mode="suffix">\i0</xsl:template>

</xsl:stylesheet>

当使用'后缀'模式时,<xsl:sort order="descending" />以相反的顺序处理属性。

严格地说,主模板中间的select="node()"是多余的,但是在阅读时只会处理节点而不是属性时会更清楚。

您可以通过使用以下内容替换现有的suffix模式模板来更轻松地添加新属性:

<xsl:template match="@*" mode="suffix">
  <xsl:apply-templates select="." mode="prefix" />
  <xsl:text>0</xsl:text>
</xsl:template>

这只使用前缀的模板,并在末尾添加额外的0。如果某些属性不能像这样一般地处理,你总是可以覆盖它。

答案 1 :(得分:1)

<xsl:template match="fo:block">
    <xsl:text>{</xsl:text>
        <xsl:if test="@font-weight = 'bold'">\b</xsl:if>
        <xsl:if test="@font-style = 'italic'">\i</xsl:if>

        <xsl:apply-templates />

        <xsl:if test="@font-style = 'italic'">\i0</xsl:if>
        <xsl:if test="@font-weight = 'bold'">\b0</xsl:if>
    <xsl:text>\par}</xsl:text>
</xsl:template/>

同时检查w3schools.com以获取有关XSLT的更多信息。

答案 2 :(得分:1)

此转换更通用且易于理解

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my">
 <xsl:output method="text"/>

 <xsl:template match="/*">
  <xsl:variable name="vAttributesResult">
   <xsl:call-template name="processAttributes"/>
  </xsl:variable>

  <xsl:value-of select=
   "concat(substring-before($vAttributesResult, ' '),
           .,
           substring-after($vAttributesResult, ' ')
           )
   "/>
 </xsl:template>

 <xsl:template name="processAttributes">
  <xsl:param name="pattrList" select="@*"/>
  <xsl:param name="pResult" select="' '"/>

  <xsl:choose>
      <xsl:when test="not($pattrList)">
       <xsl:value-of select="$pResult"/>
      </xsl:when>
      <xsl:otherwise>
       <xsl:variable name="vthisResult">
        <xsl:apply-templates select="$pattrList[1]">
         <xsl:with-param name="pResult" select="$pResult"/>
        </xsl:apply-templates>
       </xsl:variable>

       <xsl:call-template name="processAttributes">
        <xsl:with-param name="pattrList" select="$pattrList[position()>1]"/>
        <xsl:with-param name="pResult" select="$vthisResult"/>
       </xsl:call-template>
      </xsl:otherwise>
  </xsl:choose>
 </xsl:template>

 <xsl:template match="@font-weight[.='bold']">
  <xsl:param name="pResult"/>
  <xsl:value-of select="concat('\b', $pResult, '\b0')"/>
 </xsl:template>

 <xsl:template match="@font-style[.='italic']">
  <xsl:param name="pResult"/>
  <xsl:value-of select="concat('\i', $pResult, '\i0')"/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档(更正格式正确):

<fo:block font-weight="bold" font-style="italic"
xmlns:fo="some:fo">Some Text Here</fo:block>

生成了想要的结果

\i\bSome Text Here\b0\i0

请注意

  1. 您可以根据需要为多个新的属性/值组合轻松添加处理 - 只需为新属性添加新模板。

  2. 如果订单很重要,请使用这些模板处理属性:

  3. -

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
    
        <xsl:template match="/*">
            <xsl:text>{</xsl:text>
            <xsl:apply-templates select="@*">
             <xsl:with-param name="pSuff" select="''"/>
             <xsl:sort select="position()"/>
            </xsl:apply-templates>
    
            <xsl:apply-templates select="node()" />
    
            <xsl:apply-templates select="@*">
             <xsl:with-param name="pSuff" select="'0'"/>
             <xsl:sort select="position()" order="descending"/>
            </xsl:apply-templates>
    
            <xsl:text>\par}</xsl:text>
        </xsl:template>
    
        <xsl:template match="@font-weight['bold']">
          <xsl:param name="pSuff"/>
          <xsl:value-of select="concat('\b',$pSuff)"/>
        </xsl:template>
    
        <xsl:template match="@font-style['italic']">
          <xsl:param name="pSuff"/>
          <xsl:value-of select="concat('\i',$pSuff)"/>
        </xsl:template>
    </xsl:stylesheet>
    

    这种转换借用了@Flynn1169的答案,并大大简化了它(只有3个模板而不是t,没有模式),最重要的是,根据属性的词汇顺序显示结果。

    在这种情况下,结果匹配属性的词法顺序,而不是它们的排序名称! :

    如果我们有这个XML文档

        <fo:block font-style="italic" font-weight="bold" 
    xmlns:fo="some:fo">Some Text Here</fo:block>
    

    结果现在是:

    {\i\bSome Text Here\b0\i0\par}
    

    备注:虽然XPath数据模型中没有“属性顺序”,但我在推式模式下使用的所有XSLT处理器(超过9个)都会产生处理结果属性根据它们的词汇顺序。