基于XML Editor 19.1与Saxon PE 9.7的XSLT节点匹配显示需求问询
搞定你的两个XSLT需求!
嘿,我先帮你捋捋,首先你现有代码里的<xsl:when>测试条件有语法错误——.[@n]/$div4tablet这种写法是不生效的,应该是对$div4tablet做translate处理去掉#符号,才能和surface的@xml:id正确匹配。下面我针对你的两个需求,把代码补全并解释清楚:
需求1:当两个节点相等时,显示第一个节点的子节点
我默认这里的“两个节点相等”指的是多个div4节点的@n属性值重复,这种情况下只显示同组里第一个节点的子节点。如果你的“相等”是指其他匹配规则(比如div4和对应surface的@n一致),后面我会说明怎么调整。
需求2:匹配surface/@xml:id与div/@facs时,在对应<surface>后显示graphic/@url
核心是通过div4的@facs(去掉开头的#)找到对应的surface节点,然后提取它下面的graphic/@url。
完整可运行的代码片段
<xsl:for-each select="descendant-or-self::div3[@type='col']/div4[@n]"> <xsl:variable name="div4tablet" select="@facs"/> <!-- 去掉@facs里的#,得到用于匹配的纯ID --> <xsl:variable name="targetSurfaceId" select="translate($div4tablet, '#', '')"/> <!-- 定位到对应的surface节点 --> <xsl:variable name="matchedSurface" select="preceding::facsimile/surfaceGrp[@type='tablet']/surface[@xml:id = $targetSurfaceId]"/> <!-- 需求1:判断当前div4是否是同@n的第一个节点 --> <xsl:if test="generate-id() = generate-id(preceding-sibling::div4[@n = current()/@n][1])"> <!-- 复制第一个节点的所有子节点 --> <xsl:copy-of select="*"/> </xsl:if> <!-- 需求2:如果找到匹配的surface,输出对应的graphic URL --> <xsl:if test="$matchedSurface"> <xsl:for-each select="$matchedSurface"> <!-- 这里可以根据需要调整输出格式,比如包装成img标签 --> <xsl:text>对应surface的图片链接:</xsl:text> <xsl:value-of select="graphic/@url"/> <xsl:text> </xsl:text> <!-- 换行,让输出更整洁 --> </xsl:for-each> </xsl:if> </xsl:for-each>
关键细节说明
- 修正匹配逻辑:
translate($div4tablet, '#', '')会把@facs里的#(比如#surf_001)去掉,得到surf_001,这样就能和surface的@xml:id精准匹配了。 - 需求1的灵活调整:如果你的“两个节点相等”是指
div4的@n和对应surface的@n相等,只需要把<xsl:if>里的条件改成:<xsl:if test="@n = $matchedSurface/@n"> <xsl:copy-of select="*"/> </xsl:if> - 需求2的输出自定义:如果想把URL做成可显示的图片,直接替换成HTML标签即可:
<img src="{graphic/@url}" alt="Surface {../@xml:id} 对应的图片"/> - 性能优化:如果
facsimile节点不在div4的前置轴里,直接写绝对路径(比如/TEI/facsimile)代替preceding::facsimile,查找速度会更快。
内容的提问来源于stack exchange,提问作者Vanessa
相关产品推荐
相关产品推荐

