【问题标题】:xsl: when two nodes are equal, display child of first nodexsl:当两个节点相等时,显示第一个节点的子节点
【发布时间】:2018-04-30 00:47:15
【问题描述】:

我正在使用 XML Editor 19.1,Saxon P.E 9.7。

对于每个选定的div,如果surface/@xml:id = div/@facs,我希望在每个<surface> 之后显示graphic/@url。

XSL

 <xsl:for-each select="descendant-or-self::div3[@type='col']/div4[@n]">
  <xsl:variable name="div4tablet" select="@facs"/>
   <xsl:choose>
    <xsl:when test="translate(.[@n]/$div4tablet, '#', '') = preceding::facsimile/surfaceGrp[@type='tablet']/surface[@n]/@xml:id">
     <xsl:value-of select=""/> <!-- DISPLAY graphic/@url that follows facsimile/surfaceGrp/surface -->
    </xsl:when>
    <xsl:otherwise/>
   </xsl:choose>
  [....]
 </xsl:for-each> 

TEI 示例

 <facsimile>     
  <surfaceGrp n="1" type="tablet">
   <surface n="1.1" xml:id="ktu1-2_i_1_to_10_img">
    <graphic url="../img/KTU-1-2-1-10-recto.jpg"/>
    <zone xml:id=""/>
    <zone xml:id=""/>
   </surface>
    <surface n="1.2" xml:id="ktu1-2_i_10_to_30_img">
    <graphic url="../img/KTU-1-2-10-30-recto.jpg"/>
    <zone xml:id=""/>
   </surface>
   [...]
  </surfaceGrp>
  <surfaceGrp n="2">
  [...]
  </surfaceGrp>
 </facsimile>


 <text>
  [...]
  <div3 type="col">
   <div4 n="1.2.1-10" xml:id="ktu1-2_i_1_to_10" facs="#ktu1-2_i_1_to_10_img">
    [...]
   </div4>
   <div4 n="1.2.10-30" xml:id="ktu1-2_i_10_to_30" facs="#ktu1-2_i_10_to_30_img">
    [...]
   </div4>
  </div3>
 </text> 

我尝试过&lt;xsl:value-of select="preceding::facsimile/surfaceGrp[@type='tablet']/surface[@n, @xml:id]/graphic/@url"/&gt;,但它显示了所有graphic/@url,而不仅仅是fascsimile/surfaceGrp/surface 后面的那个。 所以我的问题是:如何为每个div3[@type='col']/div4[@n] 只显示surface/graphic/@url?

提前感谢您的帮助。

【问题讨论】:

    标签: xslt tei


    【解决方案1】:

    当您使用 XSLT 2 或 3 并且元素具有 xml:id 属性时,您甚至不需要密钥,但可以使用 id 函数:

      <xsl:template match="div4">
          <div>
              <xsl:value-of select="id(substring(@facs, 2))/graphic/@url"/>
          </div>
      </xsl:template>
    

    我将id 的使用放入与div4 元素匹配的模板中,但您当然可以在for-each 中选择这些元素以同样的方式使用它。

    在https://xsltfiddle.liberty-development.net/bdxtpR 上查看最小但完整的示例。

    【讨论】:

    • 太棒了!谢谢@马丁!它工作得很好。我还将尝试为每个div4/l[@n] 应用id 为zone。
    【解决方案2】:

    对于此类问题,您应该使用xsl:key。

    首先,我们必须为目标节点声明一个键

    <xsl:key name="kSurface" match="surface" use="concat('#', @xml:id)"/>
    

    注意这里使用了concat 函数,一个# 被添加到xml:id 中,这样键就会显示为:

    #ktu1-2_i_1_to_10_img
    #ktu1-2_i_10_to_30_img
    

    现在在这个循环中:

    <xsl:for-each select="descendant-or-self::div3[@type='col']/div4[@n]">
    

    我们可以通过以下方式访问与@facs 属性匹配的键:

     <xsl:value-of select="key('kSurface', @facs)/graphic/@url"/>
    

    整个样式表如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        version="1.0">
    
        <xsl:output omit-xml-declaration="yes"/>
    
        <xsl:key name="kSurface" match="surface" use="concat('#', @xml:id)"/>
    
        <xsl:template match="/">
            <xsl:for-each select="descendant-or-self::div3[@type='col']/div4[@n]">
                <xsl:value-of select="key('kSurface', @facs)/graphic/@url"/>
                <xsl:text>&#xA;</xsl:text>
            </xsl:for-each> 
        </xsl:template>
    
    </xsl:stylesheet>
    

    看到它在行动here。

    【讨论】:

    • 谢谢@乔尔!!你的解释很有用。我总是对key 有疑问。但是,我认为@Martin 建议的id 在这里是相关的。
    猜你喜欢
    • 2014-02-11
    • 1970-01-01
    • 2014-08-06
    • 2013-02-11
    • 1970-01-01
    • 2020-05-28
    • 2022-06-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多