1

我有 2 个 xml 文档:

  1. 包含小型内联 img 的技术文章
  2. 一个文件,其中包含 img 文件,它们是文章中小图像的全尺寸版本。我将此文件称为“辅助文件”。

我的目标是使用 xsl 来更新文章中的 xml,这样,我就有了 2 个 img,而不是每个图都有一个 img ......最初在文章 xml 中编码的小的一个,以及相应的较大的一个。这两个 img 都将是新元素 image-set 的子元素。

所以这里是“之前”和“之后”的情况:

前:

<figure>
   <heading alttoc="" refname="fig1" type="figure">Figure 1. netserver on SUT in out
      of the box configuration</heading>
   <img alt="netserver on SUT in out-of-the-box configuration" 
        height="288" src="figure1.jpg" width="572"/>
</figure>

后:

<figure>
   <heading alttoc="" refname="fig1" type="figure">Figure 1. netserver on SUT in out
      of the box configuration</heading>
         <image-set>
                <img alt="netserver on SUT in out-of-the-box configuration" 
                     height="288" src="figure1.jpg" width="572"/>
                <img alt="netserver on SUT in out-of-the-box configuration" 
                     height="456" src="figure1_ian.jpg" width="905"/>
         <!--The figureNumber is: 1-->
         </image-set>
</figure>

另一个 XSL 会将更新的文章 XML 文件转换为 HTML。较小的 img 将像以前一样内联显示,但是当用户单击“查看完整尺寸版本”链接时,较大的 img 将在叠加层中可用。

问题描述:每篇文章可以包含多张图片。每个边文件可以包含许多图像。我必须将侧文件中的正确图像与文章文件中的图像匹配。我正在使用 xsl:number 创建一个变量,为每个 img 存储一个与每个图像在文章文件中出现的顺序相对应的数字,并且我试图在 document() 函数中将该变量引用为在侧文件中获取正确 img 的谓词。它不工作:

这是用于存储订单的变量:

<xsl:variable name="figureNumber">
        <xsl:number />
</xsl:variable>

下面是 document() 函数的代码,该函数不适用于变量:

<!-- Output the larger version of the same img that sits in the sidefile.
The "/" as the second argument causes processor to look for the  sidefile 
in same folder as the article xml file. -->
<xsl:copy-of select="document('sidefile.xml',/)//figure[$figureNumber]/img" />
<xsl:comment>The figureNumber is: <xsl:value-of select="$figureNumber"/></xsl:comment>

当我运行它时,我不是只从辅助文件中获取我想要的 img(在上面的示例中,我应该只获取第一张图像,或 img[1]),而是在辅助文件中获取所有 img:

<figure>
  <heading alttoc="" refname="fig1" type="figure">Figure 1. netserver on SUT in out
    of the box configuration</heading>
  <image-set>
    <img alt="netserver on SUT in out-of-the-box configuration" 
         height="288" src="figure1.jpg" width="572"/>
    <img alt="netserver on SUT in out-of-the-box configuration" 
         height="456" src="figure1_ian.jpg" width="905"/>
    <img alt="netperf on SUT in out-of-the-box configuration" 
         height="456" src="figure2_ian.jpg" width="905"/>
    <img alt="netperf and netserver (bidirectional) on SUT out of the box" 
         height="456" src="figure3_ian.jpg" width="905"/>
    <img alt="netserver, out of the box with numactl" 
         height="456" src="figure4_ian.jpg" width="905"/>
    <img alt="netperf, out of the box with numactl" 
         height="456" src="figure5_ian.jpg" width="905"/>
    <img alt="netperf and netserver (bidirectional), out of the box with numactl" 
         height="456" src="figure6_ian.jpg" width="905"/>
    <img alt="netserver, Ethernet SMP IRQ affinity, no irqbalance" 
         height="456" src="figure7_ian.jpg" width="905"/>
    <img alt="netperf, Ethernet SMP IRQ affinity, no irqbalance" 
         height="456" src="figure8_ian.jpg" width="905"/>
    <img alt="netperf and netserver (bidirectional), Ethernet SMP IRQ affinity, no irqbalance" 
         height="456" src="figure9_ian.jpg" width="905"/>
    <img alt="netserver, Ethernet SMP IRQ affinity and numactl, no irqbalance" 
         height="456" src="figure10_ian.jpg" width="905"/>
    <img alt="netperf, Ethernet SMP IRQ affinity and numactl, no irqbalance" 
         height="456" src="figure11_ian.jpg" width="905"/>
    <img alt="Bidirectional,  Ethernet SMP IRQ affinity and numactl, no irqbalance" 
         height="456" src="figure12_ian.jpg" width="905"/>
    <img alt="netserver, Ethernet SMP IRQ affinity, no irqbalance, bonded interfaces" 
         height="456" src="figure13_ian.jpg" width="905"/>
    <img alt="netserver, Ethernet SMP IRQ affinity, no irqbalance, with and without bonding" 
         height="456" src="figure14_ian.jpg" width="905"/>
    <!--The figureNumber is: 1-->
  </image-set>
</figure>

但是,当我在 document() 函数中对谓词进行硬编码时,我只能得到正确的 img(如上面的“After”示例):

<xsl:copy-of select="document('sidefile.xml',/)//figure[1]/img" />

我正在使用 oXygen 14.2 并尝试使用 XALAN 和 SAXON 进行此转换,结果相同。

我究竟做错了什么?

2013 年 8 月 19 日更新:

从那以后,我尝试了另一种在边文件中找到正确位置的方法,但再次让 document() 函数与其中的变量一起工作也没有运气。与我之前的方法(使用偏移量)一样,当我用文字替换 document() 函数中的变量时,它可以工作。

这有效:

<xsl:copy-of select="document('sidefile.xml',/)/dw-document/dw-sidefile/docbody/figure/img[preceding::heading[1]/@refname = 'fig1']" />

这不会:

<xsl:copy-of select="document('sidefile.xml',/)/dw-document/dw-sidefile/docbody/figure/img[preceding::heading[1]/@refname = $figureRef]" />

$figureRef 变量定义如下: 用文章文件中某个图形元素的指针,抓取该图形后面第一个锚点的@href值中'#'后面的字符串;然后,用单引号括起来:

<xsl:variable name="figureRef" select="concat($singleQuote,substring-after(following::a[1]/@href,'#'),$singleQuote)"/>

下面是文章文件中显示这些元素的 xml 片段:

<figure>
    <heading alttoc="" refname="fig1" type="figure">Figure 1. netserver on SUT in out of the box configuration</heading>
<img alt="netserver on SUT in out-of-the-box configuration" height="288" src="figure1.jpg" width="572"/>
</figure>
<p><b><a href="http://www.ibm.com/developerworks/library/l-scalability/sidefile.html#fig1">Enlarge Figure 1.</a></b></p>

...而且我知道 figureRef 变量正在解析为文章中每个图形的正确值,因为我在 document 函数之前添加了 xsl:comment's 以验证它的值是否应该是:

<xsl:when test="not(image-set)">
            <xsl:element name="figure">
                <xsl:apply-templates select="heading" />
                <xsl:element name="image-set">
                    <!-- Output the img element that was inside the original figure element -->
                    <xsl:apply-templates select="img" />
                    <!-- Output the larger version of the same img that sits in the
                        sidefile.  The "/" as the second argument causes processor to look for the
                        sidefile in same folder as the article xml file. -->
                    <xsl:comment>The figureRef is: <xsl:value-of select="$figureRef"/></xsl:comment>
                    <xsl:copy-of
                        select="document('sidefile.xml',/)/dw-document/dw-sidefile/docbody/figure/img[preceding::heading[1]/@refname = $figureRef]" />
                    <xsl:comment>The figureNumber is: <xsl:value-of select="$figureNumber"/></xsl:comment>                        
                </xsl:element>
            </xsl:element>
        </xsl:when>

...您可以从下面的结果文档片段中看到它是正确的(在第一个之后应该有另一个 img 元素):

<image-set>
    <img alt="netserver on SUT in out-of-the-box configuration" height="288" src="figure1.jpg" width="572"/>
    <!--The figureRef is: 'fig1'-->
    <!--The figureNumber is: 1-->
</image-set>

嘘。这是一个显示侧文件结构的 xml 片段:

<figure>
    <heading alttoc="" refname="fig1" type="figure">Figure 1. netserver on SUT in out
      of the box configuration</heading>
    <img alt="netserver on SUT in out-of-the-box configuration" height="456" src="figure1_ian.jpg" width="905"/>
  </figure>

  <!-- Spacer  -->
  <br/>
  <br/>
  <!-- Return link -->
  <p>
    <a href="index.html#fig1">Return to article</a>
  </p>
  <!-- Spacer -->
  <br/>

  <figure>
    <heading alttoc="" refname="fig2" type="figure">Figure 2. netperf on SUT in out of
      the box configuration</heading>
    <img alt="netperf on SUT in out-of-the-box configuration" height="456" src="figure2_ian.jpg" width="905"/>
  </figure>
4

2 回答 2

1

您做错的第一件事是试图通过偏移量来链接事物——大约五十年来,它一直是最简单的实现链接形式,也是最脆弱和最容易出错的形式。任何东西发生变化时它都会破裂,当它破裂时,它会无声地破裂,这使得它非常危险。这只是自找麻烦;不要这样做。(看到这里的这个伤疤吗?那里的那个伤疤?我让那些试图使基于偏移的链接可靠地工作的人。从我的悲伤和眼泪中学习!)

如果(如在您的示例中),小图像和大图像具有相同的alt属性并且图像文件名是系统相关的,那么您将获得更好的结果,例如

<xsl:variable name="alt" select="@alt"/>
<xsl:copy-of select="document('side-file.xml',/)
                     //img[@alt = $alt]"/>

或者,对文件名进行完整性检查:

<xsl:variable name="fn-small" select="@src"/>
<xsl:variable name="fn-big" 
              select="document('side-file.xml',/)
                     //img[@alt = $alt]/
                     @src"/>
<xsl:if test="substring-before($fn-small,'.jpg')
             != substring-before($fn-big,'_ian.jpg')">
  <xsl:message>Problems with image <xsl:value-of 
    select="concat($fn-small, ' / ', $fn-big)"/>.</xsl:message>
</xsl:if>

但是,如果您的主文件和副文件确实确实可靠地将小图像和大图像以相同的顺序排列,那么您尝试的方法就可以工作。(至少,直到第一次任何一个文档中的任何内容都更改了数字的顺序或数量。)由于您显示的主文件很少,而没有显示任何副文件,因此很难确切知道您的代码出了什么问题,但有一些明显的事情需要检查:

  • <xsl:number/>默认为<xsl:number level="single" .../>-- 因此,如果您的主文档中的所有数字都是兄弟姐妹,它应该可以正常工作。(这意味着您的技术文章有 14 个数字,没有部分。请告诉我不是这样。)如果您想要一个数字的运行序列号,您需要类似的东西<xsl:number level="any"/>——我认为一些 XSLT 编码人员会写<xsl:variable name="figureNumber" select="1 + count(preceeding::figure)"/>
  • 您所写的事实document('sidefile.xml',/)//figure ...表明侧文档中的图形元素可能处于任何深度,不一定都是兄弟姐妹;如果是这样,那么选择它们[$figureNumer]永远不会起作用。回想一下 // 扩展为 /descendant-or-self::*/,因此您的表达式扩展为

    document('sidefile.xml',/)
      /descendant-or-self::*
      /child::figure[position() = $figureNumber]
      /img
    

这意味着谓词中的隐式 position() 将获取图形在其父图形子节点序列中的位置,而不是它在文档节点的图形后代中的位置。

于 2013-08-16T17:33:37.690 回答
0

多亏了一位同事非常简单的建议,问题才得以确定并得到解决。

$figureRef 变量已经是一个字符串值,所以不需要用单引号括起来。添加引号确保我永远不会得到我需要的结果集。所以....

前:

<xsl:variable name="figureRef" select="concat($singleQuote,substring-after(following::a[1]/@href,'#'),$singleQuote)"/>

后:

<xsl:variable name="figureRef"><xsl:value-of select="substring-after(following::a[1]/@href,'#')"/></xsl:variable>

在 document() 函数中使用它:

<xsl:copy-of select="document('sidefile.xml',/)/dw-document/dw-sidefile/docbody/figure/img[preceding::heading[1]/@refname = $figureRef]" />
于 2013-08-20T15:04:04.613 回答