我有一个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>
这表示一组在系统中传递的消息。在此示例中,代码键:20
,23
和30
仅存在一次,但代码键60
和61
的无限数量发生。这些标签彼此相关,并且该关系基于邻近度(即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
?
由于
答案 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,那么表达式将不会选择任何内容。