合并父上下文中的两个标记

时间:2014-08-15 12:27:17

标签: xml xslt

我有一个XSLT转换来对数据集执行某些功能。我有一个输入xml文件:

<Messages>
    <Message>
        <ID>1</ID>
        <Tag>
            <Key>20</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>23</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>61</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>61</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>30</Key>
            <Body>...</Body>
        </Tag>
    </Message>
    <Message>
        <ID>2</ID>
        <Tag>
            <Key>20</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>23</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>61</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>61</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>30</Key>
            <Body>...</Body>
        </Tag>
    </Message>
</Messages>

这表示一组在系统中传递的消息。在此示例中,代码键:202330仅存在一次,但代码键6061的无限数量发生。这些标签彼此相关,并且该关系基于邻近度(即61进行60与该标签相关)。标记键61也不是必需的,因此60可能存在而没有相关的61进行处理。

所以,我想要做的是将这些标签组合在一起以获得如下形式:

<Messages>
    <Message>
        <ID>1</ID>
        <Tag>
            <Key>20</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>23</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
            <RelatedBody>...</RelatedBody>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
            <RelatedBody>...</RelatedBody>
        </Tag>
        <Tag>
            <Key>30</Key>
            <Body>...</Body>
        </Tag>
    </Message>
    <Message>
        <ID>2</ID>
        <Tag>
            <Key>20</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>23</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
            <RelatedBody>...</RelatedBody>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
        </Tag>
        <Tag>
            <Key>60</Key>
            <Body>...</Body>
            <RelatedBody>...</RelatedBody>
        </Tag>
        <Tag>
            <Key>30</Key>
            <Body>...</Body>
        </Tag>
    </Message>
</Messages>

那么,我如何在XSLT中将每个Message转换为将60与({可选地,如消息2中的第二个60中所示)结合61

由于

1 个答案:

答案 0 :(得分:2)

任何启动的XSLT问题&#34;我想保持大部分XML相同但调整X和Y&#34;通常应该以身份模板开头,该模板复制输入XML不变,除非被更具体的行为覆盖

<xsl:template match="@*|node()">
  <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>

有了这些,您就可以为要更改的内容添加更多特定模板。首先,您可以使用

删除所有Tag元素Key 61
<xsl:template match="Tag[Key = '61']" />

现在,对于键60标签,您似乎希望按原样复制它们,但如果它们立即后跟61,则插入一个额外的元素。您可以使用模板模式非常简洁地完成此操作

<xsl:template match="Tag[Key = '60']">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()" />
    <xsl:apply-templates mode="related"
          select="following-sibling::*[1][self::Tag][Key = '61']" />
  </xsl:copy>
</xsl:template>

<xsl:template match="Tag" mode="related">
  <RelatedBody><xsl:value-of select="Body" /></RelatedBody>
</xsl:template>

这里的神奇之处在于select="following-sibling::*[1][self::Tag][Key = '61']",它会选择紧跟在此之后的元素,但,如果该元素是带有键61的Tag。如果有如果没有跟随元素,或者如果它不是Tag和键61,那么表达式将不会选择任何内容。