这是真实的场景,只有我更改了数据。我有下面的父子关系xml。我正在尝试使用XSLT转换下面的xml。我能够转换父数据,但不能给出子节点的条件,比如如果子引用在任何时候发生变化,它应该分离样本,否则它应该由子节点分离。
输入文档
<Samples>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</Sample>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childref>101</childref>
<eno>test123</eno>
<ename>someothername</ename>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<c1ref>102</c1ref>
<childref>102</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</Sample>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<c1ref>103</c1ref>
<childref>103</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</Sample>
</Samples>
OP没有解释。可能是预期的输出文档
<Samples>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childs>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</childs>
<childs>
<childref>101</childref>
<eno>test123</eno>
<ename>someothername</ename>
</childs>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<c1ref>102</c1ref>
<childs>
<childref>102</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</childs>
</Sample>
</Samples>
下面的XSLT工作,但它再次重复childref 101。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="Samples">
<xsl:copy>
<!-- select the first Sample -->
<xsl:apply-templates select="Sample[1]"/>
</xsl:copy> </xsl:template>
<xsl:template match="Sample">
<!-- the a1 attribute in Sample will act as the identifier
(check if it is the same element) -->
<xsl:variable name="identifier" select="a1"/>
<xsl:copy>
<xsl:apply-templates select="a1"/>
<xsl:apply-templates select="b1"/>
<xsl:apply-templates select="c1ref"/>
<xsl:element name="childs">
<xsl:apply-templates select="childref"/>
<xsl:apply-templates select="eno"/>
<xsl:apply-templates select="ename"/>
</xsl:element>
<!-- get childs of Sample with same identifier -->
<xsl:apply-templates
select="following-sibling::Sample[a1=$identifier]"
mode="SameElement"/>
</xsl:copy>
<!-- select the nex Samples with different identifier -->
<xsl:apply-templates select="following-sibling::Sample[a1!=$identifier][1]"/> </xsl:template>
<xsl:template match="Sample" mode="SameElement">
<!-- here only output the child elements -->
<xsl:element name="childs">
<xsl:apply-templates select="childref"/>
<xsl:apply-templates select="eno"/>
<xsl:apply-templates select="ename"/>
</xsl:element> </xsl:template>
<xsl:template match="*|@*|text()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
如何编写将产生上述输出的xslt
老实说,我无法找出XSLT中的错误。因此,我使用分层分组(Jeni Tennison描述)提出了自己的版本。这是一个XSLT1.0解决方案。如果我使用这个输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<Samples>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</Sample>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childref>101</childref>
<eno>test123</eno>
<ename>someothername</ename>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<c1ref>102</c1ref>
<childref>102</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</Sample>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<c1ref>101</c1ref>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<c1ref>103</c1ref>
<childref>103</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</Sample>
</Samples>
并应用此XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="keyByc1ref" match="Sample" use="c1ref"/>
<xsl:template match="Samples">
<xsl:variable name="uniqueSet" select="Sample[generate-id()=generate-id(key('keyByc1ref',c1ref)[1])]"/>
<Samples>
<xsl:apply-templates select="$uniqueSet" mode="group"/>
</Samples>
</xsl:template>
<xsl:template match="Sample" mode="group">
<Sample>
<xsl:copy-of select="a1"/>
<xsl:copy-of select="b1"/>
<xsl:apply-templates select="key('keyByc1ref',c1ref)" mode="item"/>
</Sample>
</xsl:template>
<xsl:template match="Sample" mode="item">
<childs>
<xsl:copy-of select="childref"/>
<xsl:copy-of select="eno"/>
<xsl:copy-of select="ename"/>
</childs>
</xsl:template>
</xsl:stylesheet>
我得到了这个XML输出。我认为它看起来不错,我不确定预期的输出:
<?xml version="1.0" encoding="UTF-8"?>
<Samples>
<Sample>
<a1>a1name</a1>
<b1>b1desc</b1>
<childs>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</childs>
<childs>
<childref>101</childref>
<eno>test123</eno>
<ename>someothername</ename>
</childs>
<childs>
<childref>101</childref>
<eno>test</eno>
<ename>somename</ename>
</childs>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<childs>
<childref>102</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</childs>
</Sample>
<Sample>
<a1>a1name1</a1>
<b1>b1desc1</b1>
<childs>
<childref>103</childref>
<eno>test1234</eno>
<ename>someothername1</ename>
</childs>
</Sample>
</Samples>
使用开头的键可以识别所有唯一的项目集。对于每个识别的组;模式=组";复制a1和b1并调用将其他3个元素复制到子节点中的项模板的模板。
这是一个分组问题,可以使用xsl:for-each-group
轻松解决。
然而,我还没有从你的例子中准确地计算出你的分组标准是什么,所以我不能给你精确的代码。