首页 文章

动态显示xml节点并使用递归将样式应用于特定节点

提问于
浏览
-4

下面是我的xml文件 .

<xml>
<top>
 <main>
    <firstname>John</firstname>
    <lastname>John</lastname>
    <table></table>
    <chapter>
       <firstname>Alex</firstname>
       <lastname>Robert</lastname>
       <p>Sample text chap</p>
       <figure name="f1.svg"></figure>
       <chapter>
          <firstname>Rebec</firstname>
          <lastname></lastname>
          <p>Sample text</p>
          <figure name="f2.svg"></figure>
       </chapter>
    </chapter>
 </main>
</top>
</xml>

Desired output:

<bold>John
table
<bold>Robert
Sample text chap
f1.svg
<bold> Rebec
Sample text
f2.svg

Explaination: 我写了一个xslt来做这件事 . 我需要动态获取xml节点 . 我不能写:xsl:apply-templates select = 'main/lastname' . 因为我的xml格式可以随时更改 . 我尝试过使用'$root/*'首先获取所有xml节点的逻辑 . 然后,如果遇到'table'元素,我使用xsl:apply-templates select = 'current()[name() = ' TABLE ']'并执行表创建操作 . 这很好用 . 我得到了所需的输出,但我的图形元素只在输出的每个位置显示f1.svg . f2.svg未显示 . 我如何只匹配'lastname'并使其变为粗体?我想使代码尽可能通用/模块化,以便它遍历xml树的所有元素,并在特定节点上进行一些格式化 . 下面是递归的xslt . 有了这个,我的数据就会重复出现 . 我正在编写递归模板,因为xslt不是顺序的 .

XSLT:

<xsl:call-template name="FetchNodes">
<xsl:with-param name="endIndex" select="$NumberOfNodes" />
<xsl:with-param name="startIndex" select="1" />
<xsl:with-param name="context" select="$root/*" />
</xsl:call-template>


<xsl:template name="FetchNodes">
    <xsl:param name="endIndex" />
    <xsl:param name="startIndex" />
    <xsl:param name="context" />
    <xsl:if test="$startIndex &lt;= $endIndex">
           <xsl:if test="$context[$startIndex][name() = 'table']"">
                  <xsl:apply-templates select="$context[$startIndex][name() = 'table']"" mode="table" />
      </xsl:if>
            <xsl:call-template name="FetchNodes">
        <xsl:with-param name="endIndex" select="$endIndex" />
        <xsl:with-param name="startIndex" select="$startIndex + 1"/>
        <xsl:with-param name="context" select="$context" />
    </xsl:call-template>
</xsl:if>
</xsl:template>

    <xsl:template match="node()" mode="table">   
       <xsl:value-of select="node()" />
    </xsl:template>

使用上面的xslt,应用模板的xpath中有些内容不正确 . 输出不合适 .
我想要XSL FO输出 .

任何人都可以提出建议吗?

1 回答

  • 1

    显示“f1.svg”而不是“f2.svg”的问题是因为这一行

    <xsl:variable name="ImageName">
        <xsl:value-of select="$root/*/chapter/figure/@name" />
    </xsl:variable>
    

    此时您已经定位在 figure 上,因此您只需要在此处使用相对xpath表达式 . 您当前使用的是绝对路径,因此无论您的上下文如何,它都将始终返回第一个 @name 属性 . 应该看看这个

    <xsl:variable name="ImageName">
        <xsl:value-of select="@name" />
    </xsl:variable>
    

    或者更好,就像这样

    <xsl:variable name="ImageName" select="@name" />
    

    话虽如此,代码在一个模板中,试图匹配一个元素 FIGURE 元素,这个元素在你向我们展示的XML中不存在 . 例如,您实际上可以简化模板匹配

    <xsl:template match="figure" mode="figure">
    

    至于使事情变粗,您只需将 font-weight 属性添加到要制作粗体的任何块 . 像这样的东西:

    <xsl:choose>
       <xsl:when test="self::lastname">
          <fo:inline font-weight="bold"><xsl:value-of select="text()" /></fo:inline>
       </xsl:when>
       <xsl:otherwise>
          <xsl:value-of select="text()" />
       </xsl:otherwise>
    </xsl:choose>
    

    EDIT: 尽管如此,你可能没有采取正确的方法解决问题 . 使用模板匹配可能会更好,利用XSLT的内置模板来浏览文档 . 基本上,只需为要匹配的每个元素编写一个模板,然后生成输出,然后继续匹配其子元素 .

    例如,要将 chapter 变为 fo:block ,请执行此操作

    <xsl:template match="chapter">
       <fo:block>
          <xsl:apply-templates/>
      </fo:block>
    </xsl:template>
    

    要以粗体输出 firstname ,请执行此操作

    <xsl:template match="firstname">
       <fo:inline font-weight="bold">
          <xsl:value-of select="text()"/>
       </fo:inline>
    </xsl:template>
    

    要将 figure 转换为图像,请执行此操作(请注意,此处使用属性值模板,花括号表示要计算的表达式,而不是字面输出)

    <xsl:template match="figure">
       <fo:block>
          <fo:external-graphic src="../resources/{@name}" content-height="60%" scaling="uniform" padding-left="2cm"/>
       </fo:block>
    </xsl:template>
    

    试试这个XSLT作为起点,并以此为基础

    <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="main">
          <fo:block>
             <xsl:apply-templates/>
          </fo:block>
       </xsl:template>
    
       <xsl:template match="chapter">
          <fo:block>
             <xsl:apply-templates/>
          </fo:block>
       </xsl:template>
    
       <xsl:template match="firstname">
          <fo:inline font-weight="bold">
             <xsl:value-of select="text()"/>
          </fo:inline>
       </xsl:template>
    
       <xsl:template match="lastname"/>
    
       <xsl:template match="figure">
          <fo:block>
             <fo:external-graphic src="../resources/{@name}" content-height="60%" scaling="uniform" padding-left="2cm"/>
          </fo:block>
       </xsl:template>
    </xsl:stylesheet>
    

相关问题