我有这样一个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>我需要引用人员中的所有节点,但我需要首先查看那些在管理人员中具有收藏属性的节点,然后再查看其他节点。我想我需要以某种方式将<xsl:apply-templates select="/people/person[/executives/executive/@id = @id]" />和<xsl:apply-templates select="/people/person[@favorite = 'yes']" />结合起来。
但我不知道怎么做。
发布于 2015-09-02 16:21:14
类似于以下几点的方法会奏效:
<!-- 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>有更好的方法来使用键来编写这个文件(Tim也给出了这样的解决方案),但是我认为这就足够了,除非您有非常大的列表,使得直接查找太慢。
我用于输出的结构应该根据您的需要进行调整。我用了额外的元素来确保你收集正确的元素。
发布于 2015-09-02 16:19:37
您可以通过使用一个键来通过name属性查找执行人员来简化事情。
<xsl:key name="execs" match="executive" use="@name" />然后,要获得在管理人员中最受欢迎的person节点,可以使用以下键
<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>发布于 2015-09-02 16:28:39
这里还有另一种看待它的方法:
XSLT1.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>https://stackoverflow.com/questions/32357990
复制相似问题