如何根据更改的图ID来映射XREF ID

时间:2018-02-20 09:07:36

标签: xslt xslt-2.0

请建议。如果数字具有相同的标签,则其ID将重新排序。例如,图3具有相同的标签值,然后下一个图(具有与图3相同的标签)将重新生成为 fig3a,fig3b等。然后XREF的HREF ID也相应地改变(图3,图3a,图3b,图3c等)。请帮助。

XML:

<article>
<floats>
<Figure id="f1"><label>Figure 1</label>The Caption text for Figure.</Figure>
<Figure id="f2"><label>Figure 2</label>The Caption text for Figure.</Figure>
<Figure id="f3"><label>Figure 3</label>The Caption text for Figure.</Figure>
<Figure id="f4"><label>Figure 3</label>The Caption text for Figure.</Figure>
<Figure id="f5"><label>Figure 3</label>The Caption text for Figure.</Figure>
<Figure id="f6"><label>Figure 4</label>The Caption text for Figure.</Figure>
<Figure id="f7"><label>Figure 4</label>The Caption text for Figure.</Figure>
<Figure id="f8"><label>Figure 3</label>The Caption text for Figure.</Figure>
<Figure id="f9"><label>Figure 5</label>The Caption text for Figure.</Figure>
</floats>
<body>
<p>The <xref href="f1">Fig. 1</xref>, <xref href="f5">Fig. 3</xref>b, and <xref href="f9">Fig. 5</xref> are giving detailed info about <xref href="f3 f6 f9">Figs 3-5</xref>.</p>
</body>
</article>

XSLT2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:template>
<!--xsl:key name="kDupLabel" match="Figure" use="label"/-->

<xsl:template match="Figure">
    <xsl:variable name="var1"><xsl:value-of select="label"/></xsl:variable>
    <xsl:variable name="var2"><xsl:value-of select="distinct-values(preceding::Figure/label)"/></xsl:variable>
    <xsl:variable name="varPresentLabel"><xsl:value-of select="concat('|', ., '|')"/></xsl:variable>
    <xsl:variable name="varPrevLabels">
        <xsl:for-each select="tokenize($var2, ' ')">
            <xsl:value-of select="concat('|', ., '|')"/>
        </xsl:for-each>
    </xsl:variable>

    <xsl:text>&#10;</xsl:text>
    <xsl:element name="Figure">
        <xsl:attribute name="id">
            <xsl:choose>
                <xsl:when test="contains($varPrevLabels, $varPrevLabels)">
                    <xsl:value-of select="concat('fig', substring-after(label, ' '))"/>
                    <xsl:call-template name="tempSubID">
                        <xsl:with-param name="varN" select="$var1"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise><xsl:value-of select="@id"/></xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template name="tempSubID">
    <xsl:param name="varN"/>
    <xsl:variable name="varCnt"><xsl:value-of select="count(preceding::Figure[label=$varN])"/></xsl:variable>
    <xsl:choose>
        <xsl:when test="number($varCnt)=1">a</xsl:when>
        <xsl:when test="number($varCnt)=2">b</xsl:when>
        <xsl:when test="number($varCnt)=3">c</xsl:when>
        <xsl:when test="number($varCnt)=4">d</xsl:when>
        <xsl:when test="number($varCnt)=5">e</xsl:when>
        <xsl:when test="number($varCnt)=6">f</xsl:when>
        <xsl:when test="number($varCnt)=7">g</xsl:when>
        <xsl:when test="number($varCnt)=8">h</xsl:when>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

必填结果:

<article><floats>
<Figure id="fig1"><label>Figure 1</label>The Caption text for Figure.</Figure>
<Figure id="fig2"><label>Figure 2</label>The Caption text for Figure.</Figure>
<Figure id="fig3"><label>Figure 3</label>The Caption text for Figure.</Figure>
<Figure id="fig3a"><label>Figure 3</label>The Caption text for Figure.</Figure><!--same label as previous, ID to be 'fig3a'-->
<Figure id="fig3b"><label>Figure 3</label>The Caption text for Figure.</Figure><!--same label as previous, ID to be 'fig3b'-->
<Figure id="fig4"><label>Figure 4</label>The Caption text for Figure.</Figure>
<Figure id="fig4a"><label>Figure 4</label>The Caption text for Figure.</Figure><!--same label as previous, ID to be 'fig4a'-->
<Figure id="fig3c"><label>Figure 3</label>The Caption text for Figure.</Figure><!--same label as previous, ID to be 'fig3c'-->
<Figure id="fig5"><label>Figure 5</label>The Caption text for Figure.</Figure></floats>
<body>
    <p>The <xref href="fig1">Fig. 1</xref>, <xref href="fig3b">Fig. 3</xref>b, and <xref href="fig5">Fig. 5</xref> are giving detailed info about <xref href="fig3 fig4 fig5">Figs 3-5</xref>.</p></body></article>

1 个答案:

答案 0 :(得分:1)

我认为您可以使用两个键,然后您需要在key函数返回的序列中找到元素的位置:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:function name="mf:number-figure">
      <xsl:param name="figure" as="element(Figure)"/>
      <xsl:variable name="figure-group" select="key('figure-label', $figure/label, root($figure))"/>
      <xsl:variable name="prefix" as="xs:string" select="'fig' || replace($figure/label, '[^0-9]+', '')"/>
      <xsl:variable name="number" as="xs:string">
          <xsl:number 
            value="index-of($figure-group/generate-id(), generate-id($figure)) - 1"
            format="a"/>          
      </xsl:variable>
      <xsl:sequence
        select="if ($figure is $figure-group[1])
                then $prefix
                else $prefix || $number"/>
  </xsl:function>

  <xsl:key name="figure-ref" match="Figure" use="@id"/>

  <xsl:key name="figure-label" match="Figure" use="label"/>

  <xsl:template match="Figure/@id">
      <xsl:attribute name="{name()}" select="mf:number-figure(..)"/>
  </xsl:template>

  <xsl:template match="xref/@href">
      <xsl:attribute name="{name()}"
        select="tokenize(., '\s+')!mf:number-figure(key('figure-ref', ., root(current())))"/>
  </xsl:template>

</xsl:stylesheet>

这是http://xsltfiddle.liberty-development.net/bFukv8k/1在线的XSLT 3,但当然关键用途也可以在XSLT 2中完成,你所需要的就是拼出xsl:mode作为身份转换,转换任何使用||concat次调用以及!for $v in exp return ...的任何使用,如http://xsltransform.hikmatu.com/b4GWV9中所述。