对相似标签进行分组的 XSLT 转换
XSLT transformation to group similar tags
我有这个 XML 和 players
和 citizens
部分。每个部分都有多个 person
标签。
<?xml version="1.0" encoding="UTF-8"?>
<test>
<players>
<person>
<name>joe</name>
<age>20</age>
</person>
<person>
<name>sam</name>
<age>23</age>
</person>
</players>
<citizens>
<person>
<name>joe</name>
<city>ny</city>
</person>
<person>
<name>sam</name>
<city>london</city>
</person>
</citizens>
</test>
现在我想对此进行转换,以便根据 name
标签将 players
和 citizens
部分的 person
标签合并在一起。
这是我需要的输出。
<?xml version="1.0" encoding="UTF-8"?>
<test>
<players>
<person>
<name>joe</name>
<age>20</age>
<city>ny</city>
</person>
<person>
<name>sam</name>
<age>23</age>
<city>london</city>
</person>
</players>
</test>
我想为此做一个 XSLT 转换。我尝试了很多东西但没有运气。感谢对此的一些帮助。
更新:我试过了。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="citizens" select="/test/citizens"/>
<xsl:template match="/test/players">
<players>
<xsl:apply-templates select="person"/>
</players>
</xsl:template>
<xsl:template match="person">
<xsl:variable name="data1" select="."/>
<xsl:variable name="data2" select="/test/citizens/person[name=current()/name]/."/>
<person>
<xsl:copy-of select="$data1/*"/>
<xsl:for-each select="$data2/*">
<xsl:variable name="element2" select="name(.)"/>
<xsl:if test="count($data1/*[name()=$element2])=0">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</person>
</xsl:template>
</xsl:stylesheet>
几乎是正确的。我只想去掉最后 2 个 person
标签。请指导我。
<players>
<person>
<name>joe</name>
<age>20</age>
<city>ny</city>
</person>
<person>
<name>sam</name>
<age>23</age>
<city>london</city>
</person>
</players>
<person>
<name>joe</name>
<city>ny</city>
</person>
<person>
<name>sam</name>
<city>london</city>
</person>
这是您可以查看的一种方式:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="person-by-name" match="person" use="name" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/test">
<xsl:copy>
<xsl:apply-templates select="players"/>
</xsl:copy>
</xsl:template>
<xsl:template match="person">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="key('person-by-name', name, ../../citizens)/city "/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是另一个:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/test">
<xsl:copy>
<players>
<xsl:for-each-group select="*/person" group-by="name">
<person>
<xsl:copy-of select="name"/>
<xsl:copy-of select="current-group()/*[not(self::name)]"/>
</person>
</xsl:for-each-group>
</players>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我有这个 XML 和 players
和 citizens
部分。每个部分都有多个 person
标签。
<?xml version="1.0" encoding="UTF-8"?>
<test>
<players>
<person>
<name>joe</name>
<age>20</age>
</person>
<person>
<name>sam</name>
<age>23</age>
</person>
</players>
<citizens>
<person>
<name>joe</name>
<city>ny</city>
</person>
<person>
<name>sam</name>
<city>london</city>
</person>
</citizens>
</test>
现在我想对此进行转换,以便根据 name
标签将 players
和 citizens
部分的 person
标签合并在一起。
这是我需要的输出。
<?xml version="1.0" encoding="UTF-8"?>
<test>
<players>
<person>
<name>joe</name>
<age>20</age>
<city>ny</city>
</person>
<person>
<name>sam</name>
<age>23</age>
<city>london</city>
</person>
</players>
</test>
我想为此做一个 XSLT 转换。我尝试了很多东西但没有运气。感谢对此的一些帮助。
更新:我试过了。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="citizens" select="/test/citizens"/>
<xsl:template match="/test/players">
<players>
<xsl:apply-templates select="person"/>
</players>
</xsl:template>
<xsl:template match="person">
<xsl:variable name="data1" select="."/>
<xsl:variable name="data2" select="/test/citizens/person[name=current()/name]/."/>
<person>
<xsl:copy-of select="$data1/*"/>
<xsl:for-each select="$data2/*">
<xsl:variable name="element2" select="name(.)"/>
<xsl:if test="count($data1/*[name()=$element2])=0">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</person>
</xsl:template>
</xsl:stylesheet>
几乎是正确的。我只想去掉最后 2 个 person
标签。请指导我。
<players>
<person>
<name>joe</name>
<age>20</age>
<city>ny</city>
</person>
<person>
<name>sam</name>
<age>23</age>
<city>london</city>
</person>
</players>
<person>
<name>joe</name>
<city>ny</city>
</person>
<person>
<name>sam</name>
<city>london</city>
</person>
这是您可以查看的一种方式:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="person-by-name" match="person" use="name" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/test">
<xsl:copy>
<xsl:apply-templates select="players"/>
</xsl:copy>
</xsl:template>
<xsl:template match="person">
<xsl:copy>
<xsl:apply-templates/>
<xsl:copy-of select="key('person-by-name', name, ../../citizens)/city "/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这是另一个:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/test">
<xsl:copy>
<players>
<xsl:for-each-group select="*/person" group-by="name">
<person>
<xsl:copy-of select="name"/>
<xsl:copy-of select="current-group()/*[not(self::name)]"/>
</person>
</xsl:for-each-group>
</players>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>