根据一组其他元素中是否存在相同属性对选择进行排序
Make an ordering in a selection based on the presence of equal attribute in a set of other elements
我有这样的 XML 结构:
<people>
<person id="1" name="Sam" />
<person id="2" name="Dan" />
</people>
<executives>
<executive id="1" name="Sam" favorite="yes" />
<executive id="3" name="Ian" />
</executives>
我需要引用 people 中的所有节点,但我需要先浏览那些在 executives[=] 中有收藏夹 属性 的节点21=],然后剩下的。我想我需要以某种方式结合 <xsl:apply-templates select="/people/person[/executives/executive/@id = @id]" />
和 <xsl:apply-templates select="/people/person[@favorite = 'yes']" />
.
但是我不知道怎么办。
您可以通过使用键通过 name
属性
查找高管来简化事情
<xsl:key name="execs" match="executive" use="@name" />
然后,要得到高管喜欢的person
个节点,可以这样使用key
<xsl:apply-templates select="person[key('execs', @name)/@favorite = 'yes']" />
你会否定获得其他人的条件。
假设您有一个格式良好的 XML(即具有根元素),试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="execs" match="executive" use="@name" />
<xsl:template match="/">
<people>
<xsl:apply-templates select="//people" />
</people>
</xsl:template>
<xsl:template match="people">
<favorites>
<xsl:apply-templates select="person[key('execs', @name)/@favorite = 'yes']" />
</favorites>
<other>
<xsl:apply-templates select="person[not(key('execs', @name)/@favorite = 'yes')]" />
</other>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
像下面这样的东西会起作用:
<!-- your root here, which you didn't show in the question -->
<xsl:template match="/root">
<xsl:apply-templates select="people" />
</xsl:template>
<xsl:template match="people">
<xsl:apply-templates select="person" mode="fav"/>
<xsl:apply-templates select="person" mode="other"/>
</xsl:template>
<xsl:template match="person[@id = ../../executives/executive[@favorite = 'yes']/@id]" mode="fav">
<favorite>
<xsl:copy-of select="." />
<favorite>
</xsl:template>
<!-- not a favorite -->
<xsl:template match="person" mode="fav" />
<!-- not a non-favorite -->
<xsl:template match="person" mode="other" />
<xsl:template match="person[not(@id = ../../executives/executive[@favorite = 'yes']/@id)]" mode="other">
<non-favorite>
<xsl:copy-of select="." />
<non-favorite>
</xsl:template>
有更好的方法可以使用键来编写此代码(蒂姆同时给出了这样的解决方案),但我认为这就足够了,除非你有非常大的列表使得直接查找速度太慢。
我用于输出的结构应该根据您的需要进行调整。我使用了额外的元素来确保您收集到正确的元素。
这是另一种看待它的方式:
XSLT 1.0
<xsl:stylesheet version="1.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="x" match="executive" use="@id" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="people">
<xsl:copy>
<xsl:apply-templates select="person">
<xsl:sort select="number(key('x', @id)/@favorite='yes')" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
测试输入
<root>
<people>
<person id="1" name="Adam" />
<person id="2" name="Betty" />
<person id="4" name="David" />
<person id="5" name="Eve" />
<person id="6" name="Frank" />
<person id="7" name="George" />
</people>
<executives>
<executive id="3" name="Cecil" favorite="yes" />
<executive id="5" name="Eve" />
<executive id="6" name="Frank" favorite="yes" />
</executives>
</root>
结果
<?xml version="1.0" encoding="UTF-8"?>
<root>
<people>
<person id="6" name="Frank"/>
<person id="1" name="Adam"/>
<person id="2" name="Betty"/>
<person id="4" name="David"/>
<person id="5" name="Eve"/>
<person id="7" name="George"/>
</people>
<executives>
<executive id="3" name="Cecil" favorite="yes"/>
<executive id="5" name="Eve"/>
<executive id="6" name="Frank" favorite="yes"/>
</executives>
</root>
我有这样的 XML 结构:
<people>
<person id="1" name="Sam" />
<person id="2" name="Dan" />
</people>
<executives>
<executive id="1" name="Sam" favorite="yes" />
<executive id="3" name="Ian" />
</executives>
我需要引用 people 中的所有节点,但我需要先浏览那些在 executives[=] 中有收藏夹 属性 的节点21=],然后剩下的。我想我需要以某种方式结合 <xsl:apply-templates select="/people/person[/executives/executive/@id = @id]" />
和 <xsl:apply-templates select="/people/person[@favorite = 'yes']" />
.
但是我不知道怎么办。
您可以通过使用键通过 name
属性
<xsl:key name="execs" match="executive" use="@name" />
然后,要得到高管喜欢的person
个节点,可以这样使用key
<xsl:apply-templates select="person[key('execs', @name)/@favorite = 'yes']" />
你会否定获得其他人的条件。
假设您有一个格式良好的 XML(即具有根元素),试试这个 XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="execs" match="executive" use="@name" />
<xsl:template match="/">
<people>
<xsl:apply-templates select="//people" />
</people>
</xsl:template>
<xsl:template match="people">
<favorites>
<xsl:apply-templates select="person[key('execs', @name)/@favorite = 'yes']" />
</favorites>
<other>
<xsl:apply-templates select="person[not(key('execs', @name)/@favorite = 'yes')]" />
</other>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
像下面这样的东西会起作用:
<!-- your root here, which you didn't show in the question -->
<xsl:template match="/root">
<xsl:apply-templates select="people" />
</xsl:template>
<xsl:template match="people">
<xsl:apply-templates select="person" mode="fav"/>
<xsl:apply-templates select="person" mode="other"/>
</xsl:template>
<xsl:template match="person[@id = ../../executives/executive[@favorite = 'yes']/@id]" mode="fav">
<favorite>
<xsl:copy-of select="." />
<favorite>
</xsl:template>
<!-- not a favorite -->
<xsl:template match="person" mode="fav" />
<!-- not a non-favorite -->
<xsl:template match="person" mode="other" />
<xsl:template match="person[not(@id = ../../executives/executive[@favorite = 'yes']/@id)]" mode="other">
<non-favorite>
<xsl:copy-of select="." />
<non-favorite>
</xsl:template>
有更好的方法可以使用键来编写此代码(蒂姆同时给出了这样的解决方案),但我认为这就足够了,除非你有非常大的列表使得直接查找速度太慢。
我用于输出的结构应该根据您的需要进行调整。我使用了额外的元素来确保您收集到正确的元素。
这是另一种看待它的方式:
XSLT 1.0
<xsl:stylesheet version="1.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="x" match="executive" use="@id" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="people">
<xsl:copy>
<xsl:apply-templates select="person">
<xsl:sort select="number(key('x', @id)/@favorite='yes')" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
测试输入
<root>
<people>
<person id="1" name="Adam" />
<person id="2" name="Betty" />
<person id="4" name="David" />
<person id="5" name="Eve" />
<person id="6" name="Frank" />
<person id="7" name="George" />
</people>
<executives>
<executive id="3" name="Cecil" favorite="yes" />
<executive id="5" name="Eve" />
<executive id="6" name="Frank" favorite="yes" />
</executives>
</root>
结果
<?xml version="1.0" encoding="UTF-8"?>
<root>
<people>
<person id="6" name="Frank"/>
<person id="1" name="Adam"/>
<person id="2" name="Betty"/>
<person id="4" name="David"/>
<person id="5" name="Eve"/>
<person id="7" name="George"/>
</people>
<executives>
<executive id="3" name="Cecil" favorite="yes"/>
<executive id="5" name="Eve"/>
<executive id="6" name="Frank" favorite="yes"/>
</executives>
</root>