Xml XSL,匹配标记之间的元素

Xml XSL,匹配标记之间的元素,xml,xslt,xpath,Xml,Xslt,Xpath,我面临以下XSL转换案例 我有这个: <content> xml_and_text_0 <break/> xml_and_text_1 <break/> ... <break/> xml_and_text_n </content> xml_和_文本_0 xml_和_文本_1 ... xml和文本 我想使用XSL 2.0将上述XML转换为: <content> <block>

我面临以下XSL转换案例

我有这个:

<content>
  xml_and_text_0
  <break/>
  xml_and_text_1
  <break/>
  ...
  <break/>
  xml_and_text_n
</content>

xml_和_文本_0
xml_和_文本_1
...
xml和文本
我想使用XSL 2.0将上述XML转换为:

<content>
  <block>
    xml_and_text_0
  </block>
  <block>
    xml_and_text_1
  </block>
  ...
  <block>
    xml_and_text_n
  </block>
</content>

xml_和_文本_0
xml_和_文本_1
...
xml和文本
(我还想忽略一些_xml_和_text_k='',但现在让我们假设它们不是空的)

我想我可以使用类似于[,但可能有更简单的方法(或更简单的XPath表达式)。例如,是否可以在For each循环中匹配当前项后面/前面的所有同级

编辑:请注意,xml_和_text_i是文本和xml的混合体,类似于XHTML,我想将其包装在其中,因此类似于:

<break/>
this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation>
<break/>

这是一个很好的例子
将成为:

<block>this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation></block>
这是一个很好的例子

您的问题非常令人困惑。如果您的实际输入在
中断
节点之间同时包含元素和文本节点,那么您的示例也应该如此

显然,这个问题是关于分组和使用XSLT 2.0的,它可以很容易地解决,因为:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/content">
   <xsl:copy>
        <xsl:for-each-group select="node()" group-starting-with="break">
            <block>
                <xsl:copy-of select="current-group()[not(self::break)]" />
            </block>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

您的问题非常令人困惑。如果您的实际输入在
中断
节点之间同时包含元素和文本节点,那么您的示例也应该如此

显然,这个问题是关于分组和使用XSLT 2.0的,它可以很容易地解决,因为:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/content">
   <xsl:copy>
        <xsl:for-each-group select="node()" group-starting-with="break">
            <block>
                <xsl:copy-of select="current-group()[not(self::break)]" />
            </block>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

感谢michael.hor257k提供的解决方案(并对混淆表示抱歉)。您的方法似乎比我的方法更清晰,如下所示,并且基于XSL轴。我的版本也考虑了边缘情况,但我想您的方法也可以适用于此,我将对此进行研究

<?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="2.0">

    <!-- xsl:output method="xml" indent="yes" / -->

    <xsl:template match="/content">
        <content>

            <xsl:choose>

                <!-- First of all, distinguish the case where there is at least one separator, from the ones with no separator at all -->

                <xsl:when test="break">
                    <xsl:for-each select="break">

                        <!-- What do we have before the first separator? Create a block only if non-empty stuff -->
                        <xsl:if test="position() = 1">
                            <xsl:variable name="first_block"><xsl:copy-of select="preceding-sibling::node()" /></xsl:variable>
                            <xsl:if test = "normalize-space ( $first_block ) != ''" >
                                <xsl:message select="concat ( '1|', $first_block, '|' )" />
                                <block id = "{@id}"><xsl:copy-of select="$first_block" /></block>
                            </xsl:if>
                        </xsl:if>

                        <!-- What do we have after the next separator and before the next (or the end)? -->
                        <xsl:variable name="block_content">
                            <xsl:choose>
                                <xsl:when test="following-sibling::break">
                                    <!-- select all that comes after current node and precedes the next separator -->
                                    <xsl:copy-of select="following-sibling::node() intersect following-sibling::break[1]/preceding-sibling::node()" />
                                </xsl:when>
                                <xsl:otherwise>
                                    <!-- One separator after another, without anything in between -->
                                    <xsl:copy-of select="following-sibling::node()" />
                                </xsl:otherwise>
                            </xsl:choose>                           
                        </xsl:variable>

                        <xsl:message select="concat ( '|', $block_content, '|' )" />
                        <xsl:message select="concat ( '_|', normalize-space ( $block_content ), '|_' )" />

                        <!-- Did we get something after the current separator? Create a block if yes -->
                        <xsl:if test = "normalize-space( $block_content ) != ''">
                            <block id = "{@id}"><xsl:copy-of select="$block_content" /></block>
                        </xsl:if>                       
                    </xsl:for-each>
                </xsl:when>

                <!-- When some content is available without any separator, create a virtual single block to represent it -->
                <xsl:otherwise>
                    <xsl:variable name="single_block"><xsl:copy-of select="node()" /></xsl:variable>
                    <xsl:if test = "normalize-space( $single_block ) != ''">
                        <block id = "00"><xsl:copy-of select = "$single_block" /></block>
                    </xsl:if>
                </xsl:otherwise>
            </xsl:choose>

        </content>

    </xsl:template>

</xsl:stylesheet> 

鉴于这一投入:

<content>
    Some <b>text</b>
  <break id = '1'/>
  this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation>
  <break id = '2'/>
  Some other text
</content>

一些文本
这是一个很好的例子
其他一些文本
它产生以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<content>
    <block id="1"> Some <b>text</b></block>
    <block id="1"> this is an <ref id="123">example</ref>, which is really<citation>awesome</citation></block>
    <block id="2"> Some other text </block>
</content>

一些文本
这是一个很好的例子
其他一些文本

感谢michael.hor257k提供的解决方案(并对混淆表示抱歉)。您的方法似乎比我的方法更清晰,如下所示,并且基于XSL轴。我的版本也考虑了边缘情况,但我想您的方法也可以适用于此,我将对此进行研究

<?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="2.0">

    <!-- xsl:output method="xml" indent="yes" / -->

    <xsl:template match="/content">
        <content>

            <xsl:choose>

                <!-- First of all, distinguish the case where there is at least one separator, from the ones with no separator at all -->

                <xsl:when test="break">
                    <xsl:for-each select="break">

                        <!-- What do we have before the first separator? Create a block only if non-empty stuff -->
                        <xsl:if test="position() = 1">
                            <xsl:variable name="first_block"><xsl:copy-of select="preceding-sibling::node()" /></xsl:variable>
                            <xsl:if test = "normalize-space ( $first_block ) != ''" >
                                <xsl:message select="concat ( '1|', $first_block, '|' )" />
                                <block id = "{@id}"><xsl:copy-of select="$first_block" /></block>
                            </xsl:if>
                        </xsl:if>

                        <!-- What do we have after the next separator and before the next (or the end)? -->
                        <xsl:variable name="block_content">
                            <xsl:choose>
                                <xsl:when test="following-sibling::break">
                                    <!-- select all that comes after current node and precedes the next separator -->
                                    <xsl:copy-of select="following-sibling::node() intersect following-sibling::break[1]/preceding-sibling::node()" />
                                </xsl:when>
                                <xsl:otherwise>
                                    <!-- One separator after another, without anything in between -->
                                    <xsl:copy-of select="following-sibling::node()" />
                                </xsl:otherwise>
                            </xsl:choose>                           
                        </xsl:variable>

                        <xsl:message select="concat ( '|', $block_content, '|' )" />
                        <xsl:message select="concat ( '_|', normalize-space ( $block_content ), '|_' )" />

                        <!-- Did we get something after the current separator? Create a block if yes -->
                        <xsl:if test = "normalize-space( $block_content ) != ''">
                            <block id = "{@id}"><xsl:copy-of select="$block_content" /></block>
                        </xsl:if>                       
                    </xsl:for-each>
                </xsl:when>

                <!-- When some content is available without any separator, create a virtual single block to represent it -->
                <xsl:otherwise>
                    <xsl:variable name="single_block"><xsl:copy-of select="node()" /></xsl:variable>
                    <xsl:if test = "normalize-space( $single_block ) != ''">
                        <block id = "00"><xsl:copy-of select = "$single_block" /></block>
                    </xsl:if>
                </xsl:otherwise>
            </xsl:choose>

        </content>

    </xsl:template>

</xsl:stylesheet> 

鉴于这一投入:

<content>
    Some <b>text</b>
  <break id = '1'/>
  this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation>
  <break id = '2'/>
  Some other text
</content>

一些文本
这是一个很好的例子
其他一些文本
它产生以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<content>
    <block id="1"> Some <b>text</b></block>
    <block id="1"> this is an <ref id="123">example</ref>, which is really<citation>awesome</citation></block>
    <block id="2"> Some other text </block>
</content>

一些文本
这是一个很好的例子
其他一些文本

我不这么认为。我需要每个块都有一个新块,还有xml和text。我包含xml和text,我想在里面复制。更准确地说,它包含标记语言中的段落,类似于xhtml,所以你可以读到这样的内容:“这是一个示例,非常棒”.@zakmck请编辑您的问题,并显示上面样式表无法正确处理的示例输入。同时说明是否使用XSLT 1.0或2.0。在本例中:
一些文本这是一个示例,非常棒一些其他文本
您的XSL生成:
一些文本这是一个,非常棒一些其他文本
,但我希望:
一些文本这是一个示例,非常棒一些其他文本
请不要在评论中发布代码-编辑您的问题。请回答有关XSLT处理器版本的问题。我也编辑了我的问题,我希望