xslt - 查找每两个处理指令之间的所有XML节点

标签 xslt xpath

使用XPath或XSLT 1.0,我需要在处理指令<?start?><?end?>之间找到每个节点。如下代码:

//node()[preceding-sibling::processing-instruction()[self::processing-instruction('start')] 
following-sibling::processing-instruction()[ self::processing-instruction('end')]]`, 


可以,但是自然地,它仅选择第一个PI和最后一个PI之间的节点。有什么方法可以只选择每个开始-结束对之间的节点吗?

<root>
    abc

<?start?>def<Highlighted
    bold="yes"><Highlighted italic="yes">ghi</Highlighted></Highlighted>jkl
    <?pi?>
    <table>
      <Caption>stu</Caption>
    </table>vw

<?end?>
xy<?start?> 
abc <Caption>def</Caption> ghi<?end?> jkl
</root>

最佳答案

这是一个XSLT 2.0示例,它使用for-each-group group-starting-with/group-ending-with查找并输出这些处理指令对之间的节点:

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

<xsl:output indent="yes"/>

<xsl:template match="root">
    <xsl:for-each-group select="node()" group-starting-with="processing-instruction('start')">
        <xsl:if test="self::processing-instruction('start')">
            <group>
                <xsl:for-each-group select="current-group() except ." group-ending-with="processing-instruction('end')">
                    <xsl:sequence select="current-group()[position() ne last()]"/>
                </xsl:for-each-group>
            </group>
        </xsl:if>
    </xsl:for-each-group>
</xsl:template>

</xsl:stylesheet>


您的样本结果是

<group>def<Highlighted bold="yes">
      <Highlighted italic="yes">ghi</Highlighted>
   </Highlighted>jkl
    <?pi?>
    <table>
        <Caption>stu</Caption>
    </table>vw

    </group>
<group> 
    abc <Caption>def</Caption> ghi</group>


使用XSLT 1.0,您可以计算start pi之后和end pi之前的节点的交集:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output indent="yes"/>

    <xsl:key name="start" match="root/node()[not(self::processing-instruction('start'))]" use="generate-id(preceding-sibling::processing-instruction('start')[1])"/>
    <xsl:key name="end" match="root/node()[not(self::processing-instruction('end'))]" use="generate-id(following-sibling::processing-instruction('end')[1])"/>

    <xsl:template match="root">
        <xsl:apply-templates select="processing-instruction('start')"/>
    </xsl:template>

    <xsl:template match="processing-instruction('start')">
        <xsl:variable name="end" select="following-sibling::processing-instruction('end')[1]"/>
        <xsl:variable name="following-start" select="key('start', generate-id())"/>
        <xsl:variable name="preceding-end" select="key('end', generate-id($end))"/>
        <xsl:variable name="intersect" select="$following-start[count(. | $preceding-end) = count($preceding-end)]"/>
        <group>
            <xsl:copy-of select="$intersect"/>
        </group>
    </xsl:template>
</xsl:stylesheet>

关于xslt - 查找每两个处理指令之间的所有XML节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35769645/

相关文章:

xml - XSLT 添加新标签并复制其下的一些现有元素

html - XML 中的 XSLT 动态列

XSLT 命名空间别名在 Firefox 或 Chrome 中不起作用

xml - 如何更新System.Xml.XmlDocument中的节点值?

java - 如何获取员工 ID 并将其放入其他元素中

Java XPath 变音/元音解析

c# - 如何在 C# 中仅从 XML 文件中选择一些子节点?

php - 使用 Xpath 将 href 链接替换为来自同一父节点的字符串

xslt - 佛 :block-container and FOP compliance

java - 通过 XSTREAM 处理 XML 中不需要的元素