第一个子节点之前的字符和xslt中的最后一个子节点之后的字符

时间:2014-11-09 22:55:43

标签: xml xslt

我有以下xml:

<line>
      <orig><gap quantity="4" unit="chars" reason="illegible"/> <gap quantity="4"
      unit="chars" reason="illegible"/> <gap quantity="3" unit="chars"
      reason="illegible"/> <gap quantity="5" unit="chars" reason="illegible"/>
      shal <gap quantity="2" unit="chars" reason="illegible"/> <gap
      quantity="12" unit="chars" reason="illegible"/> </orig>
 </line>

我想对它应用一些样式,以便每次在一行中有一系列节点时,第一个间隙节点以左方括号开头,最后一个节点后面跟右方括号。将为每个间隙节点显示取自@quantity元素的多个点。例如,上面的xml应如下所示:

[.... .... .....]] [... ............]

我编写了一个模板,在第一个节点之前和最后一个节点之后添加括号,所以它看起来像这样:

[.... .... ....... shal .. ............]

我的xslt代码在这里:

<xsl:template match="tei:orig/tei:gap">
    <xsl:variable name="max" select="@quantity"/>
    <xsl:if test="not(preceding-sibling::tei:gap)">
        <xsl:text>[</xsl:text>
    </xsl:if>
    <xsl:for-each select="1 to $max">
        <xsl:text>.</xsl:text>
    </xsl:for-each>
    <xsl:if test="not(following-sibling::tei:gap)">
        <xsl:text>]</xsl:text>
    </xsl:if>        
</xsl:template>

我如何处理其他括号?我想我可以通过编写一个直接应用于节点的模板,通过升级一个级别并使用position()来实现它,但这只是将每组点包装在方括号中而不是仅包装开头和结尾每个节点序列。

编辑:我原来的样本XML令人困惑,并没有准确地解释我需要做些什么,所以希望这篇新文章在这方面会有所帮助。

2 个答案:

答案 0 :(得分:1)

如果 - 看起来 - 您正在使用XSLT 2.0,则可以使用<xsl:for-each-group>指令对相邻的gap元素进行分组。例如,以下样式表:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text" encoding="UTF-8" />
<xsl:strip-space elements="*"/>

<xsl:template match="orig">
    <xsl:for-each-group select="node()" group-adjacent="boolean(self::gap)">
        <xsl:choose>
            <xsl:when test="current-grouping-key()">
                <xsl:text>[</xsl:text>
                    <xsl:for-each select="current-group()">
                        <xsl:for-each select="1 to @quantity">
                            <xsl:text>.</xsl:text>
                        </xsl:for-each>
                        <xsl:if test="position()!=last()">
                            <xsl:text> </xsl:text>
                        </xsl:if>
                    </xsl:for-each>
                <xsl:text>]</xsl:text>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="current-group()" separator=""/>
            </xsl:otherwise>  
        </xsl:choose>
    </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>

当应用于您的(新)示例时,将返回:

[.... .... ... .....]
      shal [.. ............]

答案 1 :(得分:0)

您能否提供有关问题所在位置的更多信息?我刚刚在XSLT

之后写了一个例子
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" doctype-public="XSLT-compat" omit-xml-declaration="yes"
encoding="UTF-8" indent="no" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
    <xsl:apply-templates/>
</xsl:template>
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="hi">
   <xsl:value-of select="."/>
</xsl:template>
<xsl:template match="orig | line">
  <xsl:apply-templates/>
</xsl:template>
<xsl:template match="gap">
<xsl:variable name="max" select="@quantity"/>
<xsl:text>[</xsl:text>
<xsl:for-each select="1 to $max">
   <xsl:text>.</xsl:text>
</xsl:for-each>
<xsl:text>]</xsl:text>  
</xsl:template>
</xsl:stylesheet>

应用于输入XML

<line>
  <orig><hi>W</hi>e be <gap quantity="4" unit="chars" reason="illegible"/>
        ed and moeued of <gap quantity="6" unit="chars" reason="illegible"/>
  </orig>
</line>

生成以下输出

We be [....]ed and moeued of [......]

我只是不确定为什么在将模板应用到gap元素时需要检查前面和后面的节点,这可能只是一个误解。