使用XSLT按节点标记值拆分输入XML

使用XSLT按节点标记值拆分输入XML,xml,xslt,Xml,Xslt,我有一个输入XML,它看起来像: <Item> <text>String1</text> <format/> </Item> <Item> <text>String2</text> <format>*</format> </Item> <Item> <text>String3</text> <format>*</

我有一个输入XML,它看起来像:

<Item>
<text>String1</text>
<format/>
</Item>
<Item>
<text>String2</text>
<format>*</format>
</Item>
<Item>
<text>String3</text>
<format>*</format>
</Item>
<Item>
<text>String4</text>
<format/>
</Item>

String1
String2
*
弦3
*
弦4
输出应如下所示:

<p>String1 String2</p>
<p>String3</p>
<p>String4</p>
String1 String2

弦3

弦4

我是XSLT新手,所以不知道如何用XSLT实现这一点

我尝试使用以下内容循环浏览每个段落的所有第一个节点:

<xsl:for-each select="//Item[position()=1 or preceding-sibling::Item[1]/format='*']">

<xsl:for-each select="following-sibling::Item">
</xsl:for-each>

</xsl:for-each>

并处理以下节点,直到找到格式为“*”的“end”节点,但我不知道如何在内部“for each”中定义该条件


我想,我走错方向了。你能帮我找到正确的XSLT代码吗

在XSLT 1.0中,可以使用称为同级递归的技术:

XSLT1.0

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

<xsl:template match="/root">
    <output>
        <xsl:for-each select="Item[position()=1 or preceding-sibling::Item[1]/format='*']">
            <p>
                <xsl:apply-templates select="."/>
            </p>
        </xsl:for-each>
    </output>
</xsl:template>

<xsl:template match="Item">
    <xsl:value-of select="text"/>
    <xsl:variable name="next-item" select="following-sibling::Item[1]" />
    <xsl:if test="not(format='*') and $next-item">
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="$next-item"/>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>



请注意,这假设输入格式良好,只有一个根元素。

在XSLT 1.0中,可以使用称为同级递归的技术:

XSLT1.0

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

<xsl:template match="/root">
    <output>
        <xsl:for-each select="Item[position()=1 or preceding-sibling::Item[1]/format='*']">
            <p>
                <xsl:apply-templates select="."/>
            </p>
        </xsl:for-each>
    </output>
</xsl:template>

<xsl:template match="Item">
    <xsl:value-of select="text"/>
    <xsl:variable name="next-item" select="following-sibling::Item[1]" />
    <xsl:if test="not(format='*') and $next-item">
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="$next-item"/>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>



请注意,这假设一个格式良好的输入,只有一个根元素。

您可以像这样使用muenchien分组

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

<xsl:key name="p-group" match="Item" use="generate-id( ((.|following-sibling::Item)[format='*'][1] | .)[last()])" />

<xsl:template match="/">
  <t>
    <xsl:for-each select="t/Item[generate-id(.) = generate-id( ((.|following-sibling::Item)[format='*'][1] | .)[last()])]">
      <Item>
        <p>
          <xsl:apply-templates select="key('p-group', generate-id( ((.|following-sibling::Item)[format='*'][1] | .)[last()]))" />
        </p>
      </Item>
    </xsl:for-each>
  </t>
</xsl:template>

<xsl:template match="Item">
  <xsl:value-of select="concat(' ',text)" />
</xsl:template>

<xsl:template match="Item[not(preceding-sibling::Item[1][format != '*'])]">
  <xsl:value-of select="text" />
</xsl:template>

</xsl:transform>



您可以像这样使用muenchien分组

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

<xsl:key name="p-group" match="Item" use="generate-id( ((.|following-sibling::Item)[format='*'][1] | .)[last()])" />

<xsl:template match="/">
  <t>
    <xsl:for-each select="t/Item[generate-id(.) = generate-id( ((.|following-sibling::Item)[format='*'][1] | .)[last()])]">
      <Item>
        <p>
          <xsl:apply-templates select="key('p-group', generate-id( ((.|following-sibling::Item)[format='*'][1] | .)[last()]))" />
        </p>
      </Item>
    </xsl:for-each>
  </t>
</xsl:template>

<xsl:template match="Item">
  <xsl:value-of select="concat(' ',text)" />
</xsl:template>

<xsl:template match="Item[not(preceding-sibling::Item[1][format != '*'])]">
  <xsl:value-of select="text" />
</xsl:template>

</xsl:transform>



您可以使用XSLT 2.0吗?您可以使用XSLT 2.0吗?它正是我需要的方式。谢谢你的帮助!这正是我需要的。谢谢你的帮助!