我的输入XML文件看起来像
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
<segment id="ORC"/>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
在我上面的输入XML文件元素段 id =“ORC”是可选的
我想基于元素段将我的输入XML文件与 id =“ORC”或元素段与 id分组= “OBR”
对于上面的输入XML文件我想在元素段与id =“ORC”存在时得到以下结果
<message-group>
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
</test-message>
<test-message>
<segment id="ORC"/>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
</message-group>
对于上面的输入XML文件我希望在元素段与id =“ORC”不存在时具有以下结果
<message-group>
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
</test-message>
<test-message>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
</message-group>
我是否可以使用XSLT(2.0)模板或函数来处理上述场景
注意:我正在使用XSLT 2.0和撒克逊语解析器
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<message-group>
<xsl:for-each-group select="*" group-starting-with=
"segment[@id='ORC'][not(preceding-sibling::segment[1][@id='OBR'])]
| segment[@id='OBR'][not(preceding-sibling::segment[1][@id='ORC'])]
">
<test-message><xsl:sequence select="current-group()"/></test-message>
</xsl:for-each-group>
</message-group>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
<segment id="ORC"/>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
会产生想要的正确结果:
<message-group>
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
</test-message>
<test-message>
<segment id="ORC"/>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
</message-group>
当对此XML文档应用相同的转换(上面)时('ORC'不存在):
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
再次生成想要的正确结果:
<message-group>
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
</test-message>
<test-message>
<segment id="OBR"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
</message-group>
当对此XML文档应用相同的转换时('OBR'不存在):
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
<segment id="ORC"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
再次生成想要的正确结果:
<message-group>
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
</test-message>
<test-message>
<segment id="ORC"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
</message-group>
最后,当'ORC'和'OBR'都存在时,'OBR'先于'ORC':
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
<segment id="OBR"/>
<segment id="ORC"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
再次产生正确的,想要的结果:
<message-group>
<test-message>
<segment id="MSH"/>
<segment id="SFT"/>
<segment id="PID"/>
<segment id="NTE"/>
<segment id="NK1"/>
<segment id="PV1"/>
</test-message>
<test-message>
<segment id="OBR"/>
<segment id="ORC"/>
<segment id="NTE"/>
<segment id="OBX"/>
<segment id="NTE"/>
<segment id="SPM"/>
</test-message>
</message-group>
答案 1 :(得分:0)
快速想到两种相当简单的方法。
(1)在test-message
的模板中,包含两个test-message
输出元素,每个元素都包含apply-templates
指令。给apply-templates
一个参数来区分第一次和第二次调用。
说,像(未经测试):
<xsl:template match="test-message">
<test-message>
<xsl:apply-templates>
<xsl:with-param name="flag" select="1"/>
</xsl:apply-templates>
</test-message>
<test-message>
<xsl:apply-templates>
<xsl:with-param name="flag" select="2"/>
</xsl:apply-templates>
</test-message>
</xsl:template>
在segment
的模板中,如果(a)$ flag = 1则写出元素的副本,并且此段或任何前一个兄弟段的id都不是OBR
或{{1或者,如果(b)$ flag = 2,则此段或某个前一个兄弟段具有这样的ORC
。像
id
(2)如上所述制作<xsl:template match="segment">
<xsl:param name="flag"/>
<xsl:if test="(
$flag = 1
and not(@id = ('ORC', 'OBR'))
and not(preceding-sibling::segment
[@id=('ORC','OBR')])
) or (
$flag = 2
and ((@id = ('ORC', 'OBR'))
or preceding-sibling::segment
[@id=('ORC','OBR')]
)">
<xsl:copy-of select="."/>
</xsl:if>
模板,但在test-message
的两次调用中添加select="./segment[1]"
。
然后让xsl:apply-templates
的模板完成它的工作,然后立即重复它的兄弟姐妹。为了保持逻辑简单,我们区分了几种情况:首先,segment
我们还没有看到OBR或ORC:复制当前元素并继续前进。
$flag=1
其次,<xsl:template match="segment">
<xsl:param name="flag"/>
<xsl:choose>
<xsl:when test="$flag=1 and not(@id=('OBR', 'ORC'))">
<xsl:copy-of select="."/>
<xsl:if test="not(@id=('OBR','ORC'))">
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="flag" select="$flag"/>
</xsl:apply-templates>
</xsl:if>
</xsl:when>
我们现在遇到OBR或ORC。不要复制当前元素并且不要继续;第一个$flag = 1
元素现已完成。
test-message
第三, <xsl:when test="$flag=1 and @id=('OBR', 'ORC')">
<!--* do nothing, stop recursion *-->
</xsl:when>
我们还没有遇到过OBR或ORC。继续。
$flag = 2
第四, <xsl:when test="$flag=2 and not(@id=('OBR', 'ORC'))">
<!--* don't copy yet, keep looking for OBR/ORC *-->
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="flag" select="$flag"/>
</xsl:apply-templates>
</xsl:when>
我们现在遇到OBR或ORC。复制当前元素并继续;将标志切换到第三个值,这意味着我们在第二个$flag = 2
元素中,我们已经看到了OBR或ORC:
test-message
最后,如果 <xsl:when test="$flag=2 and @id=('OBR', 'ORC')">
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="flag" select="3"/>
</xsl:apply-templates>
</xsl:when>
,我们只需复制当前元素并继续。
$flag = 3
答案 2 :(得分:0)
如果你总是将序列分成两组,那么我想我会这样做:
<xsl:variable name="split" select="segment[@id=('ORC', 'OBR')][1]"/>
<test-message>
<xsl:copy-of select="$split/preceding-sibling::*"/>
</test-message>
<test-message>
<xsl:copy-of select="$split, $split/following-sibling::*"/>
</test-message>