我有以下XML:
<person-list>
<pid>100</pid>
<pname>Tom Jones</pname>
<pdescription>Some Text</pdescription>
<pid>101</pid>
<pname>John Thomas</pname>
</person-list>
我想得到以下结果:
<person-list>
<person>
<pid>100</pid>
<pname>Tom Jones</pname>
<pdescription>Some Text</pdescription>
</person>
<person>
<pid>101</pid>
<pname>John Thomas</pname>
</person>
</person-list>
有可能实现这个目标吗?
答案 0 :(得分:2)
在XSLT1.0中执行此操作的一种方法是定义一个键,该键将 person-list 下的非pid元素组合在第一个最前面的 pid 元素< / p>
<xsl:key
name="fields"
match="person-list/*[not(self::pid)]"
use="generate-id(preceding-sibling::pid[1])" />
然后,对于 person-list 元素,您只需选择 pid 元素
<xsl:apply-templates select="pid" />
在匹配 pid 的模板中,您将创建 person 元素,并使用键输出其他元素:
<xsl:apply-templates select="key('fields', generate-id())" />
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="fields" match="person-list/*[not(self::pid)]" use="generate-id(preceding-sibling::pid[1])" />
<xsl:template match="person-list">
<person-list>
<xsl:apply-templates select="pid" />
</person-list>
</xsl:template>
<xsl:template match="pid">
<person>
<xsl:copy-of select="." />
<xsl:apply-templates select="key('fields', generate-id())" />
</person>
</xsl:template>
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容
<person-list>
<person>
<pid>100</pid>
<pname>Tom Jones</pname>
<pdescription>Some Text</pdescription>
</person>
<person>
<pid>101</pid>
<pname>John Thomas</pname>
<pdescription></pdescription>
</person>
</person-list>
请注意,使用方法,您可以为每个人的输入文档添加更多字段,而无需修改XSLT。
另请注意使用'identity transform'复制现有元素。
答案 1 :(得分:1)
XSLT 2.0解决方案:
<xsl:template match="person-list">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="pid">
<person>
<xsl:copy-of select="current-group()"/>
</person>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
答案 2 :(得分:0)
是的,有办法做到这一点。例如,您可以找到“pid”元素,然后使用“follow-sibling”将它们与以下2个元素组合,并删除复制的标记:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/person-list/pid">
<person>
<pid><xsl:value-of select="." /></pid>
<pname><xsl:value-of select="following-sibling::*" /></pname>
<pdescription><xsl:value-of select="following-sibling::*/following-sibling::*" /> </pdescription>
</person>
</xsl:template>
<xsl:template match="/person-list/pname" />
<xsl:template match="/person-list/pdescription"/>
</xsl:stylesheet>