Обновление : Благодаря @ Flynn1179, который предупредил меня, что решение не дает желаемого результата, я немного изменил его. Теперь желаемый «хороший» формат создается .
Это преобразование XSLT 1.0 :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()[1]|@*"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match=
"xref[not(preceding-sibling::node()[1]
[self::text() and starts-with(.,',')]
)
]">
<xsl:variable name="vBreakText" select=
"following-sibling::text()[not(starts-with(.,','))][1]"/>
<xsl:variable name="vPrecedingTheBreak" select=
"$vBreakText/preceding-sibling::node()"/>
<xsl:variable name="vFollowing" select=
".|following-sibling::node()"/>
<xsl:variable name="vGroup" select=
"$vFollowing[count(.|$vPrecedingTheBreak)
=
count($vPrecedingTheBreak)
]
"/>
<sup>
<xsl:apply-templates select="$vGroup" mode="group"/>
</sup>
<xsl:apply-templates select="$vBreakText"/>
</xsl:template>
<xsl:template match="text()" mode="group">
<xsl:value-of select="normalize-space()"/>
</xsl:template>
</xsl:stylesheet>
при применении к следующемуXML-документ (на основе предоставленного, но сделан более сложным и интересным):
<p>Some text here
<xref id="1">1</xref>,
<xref id="2">2</xref>,
<xref id="3">3</xref>.
<ttt/>
<xref id="4">4</xref>,
<xref id="5">5</xref>,
<xref id="6">6</xref>.
<zzz/>
</p>
дает именно нужный, правильный результат :
<p>Some text here
<sup>1,2,3</sup>.
<ttt/>
<sup>4,5,6</sup>.
<zzz/>
</p>
Объяснение :
Мы используем «детализированное» правило идентификации, которое обрабатывает документ узел за узлом в порядке документа и копирует соответствующий узел »"как есть"
Мы переопределяем правило идентификации с помощью шаблона, который соответствует любому элементу xref
, который является первым в группе из xref
элементов, каждый из которых (кромепоследний) сопровождается непосредственным братом text-node-sibling, который начинается с символа ','.Здесь мы находим первого родственного элемента text-node, который нарушает правило (его начальный символ не ','.
Затем мы находим все узлы в группе, используя Kayessian(после @Michael Kay) формула для пересечения двух узлов. Эта формула: $ns1[count(.|$ns2) = count($ns2)]
Затем мы обрабатываем все узлы в группе в режиме с именем «группа».
Наконец, мы применяем шаблоны (в анонимном режиме) к разрывающему текстовому узлу (то есть первому узлу, следующему за группой), так что цепочка обработки продолжается.