我有一个XML文件,该文件需要对其结构进行一些更正。由于所述文档的大小,因此必须自动完成。
基本结构如下:
<body>
<div author='author1'>
<lb n='1'/>Text1
<lb n='2'/>Text2
</div>
<lb n='3'/>Text3
<lb n='4'/>Text4
<div author='author1'>
<lb n='5'/>Text5
</div>
<add>xyz</add>
<lb n='6'/>Text6
<lb n='7'/>Text7
<lb n='8'/>Text8
</body>
我想做的是将div
标记中尚未包含的所有内容放入div
标记中,并用属性@author='author2'
进行标记。移动的块的文本和结构应保持不变,只是嵌套在div
中。该顺序也必须保留。
生成的XML应该如下所示:
<body>
<div author='author1'>
<lb n='1'/>Text1
<lb n='2'/>Text2
</div>
<div author='author2'>
<lb n='3'/>Text3
<lb n='4'/>Text4
</div>
<div author='author1'>
<lb n='5'/>Text5
</div>
<div author='author2'>
<add>xyz</add>
<lb n='6'/>Text6
<lb n='7'/>Text7
<lb n='8'/>Text8
</div>
</body>
我当前的XSLT(我在注意到XML不仅包含lb
之外还编写了更多元素)确实将lb
放在了正确的div
中,但是它会将所有内容移到底部并删除文本。
XSLT看起来像这样:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" version="2.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:apply-templates select="*[not(self::lb)]"/>
<div>
<xsl:attribute name="resp">author2</xsl:attribute>
<xsl:apply-templates select="lb"/>
</div>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
它返回此XML:
<?xml version="1.0"?>
<body><div author="author1">
<lb n="1"/>Text1
<lb n="2"/>Text2
</div><div author="author1">
<lb n="5"/>Text5
</div><add>xyz</add><div resp="author2"><lb n="3"/><lb n="4"/><lb n="6"/><lb n="7"/><lb n="8"/></div></body>
我做错了什么?
感谢您的提前帮助!
答案 0 :(得分:0)
尝试在XSLT 2.0中分组
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:for-each-group select="*" group-adjacent="self::lb or self::add">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<div author='author2'>
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
答案 1 :(得分:0)
除了使用group-adjacent
之外,您还可以在group-starting-with
上使用xsl:for-each-group
尝试使用此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:for-each-group select="node()" group-starting-with="div">
<xsl:apply-templates select="." />
<xsl:if test="current-group()[2]">
<div resp="author2">
<xsl:apply-templates select="current-group()[position() gt 1]"/>
</div>
</xsl:if>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>