旧源XML:
<Employees>
<Person>
<FirstName>Joy</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Joyce</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Joe</FirstName>
<IsManager>Y</IsManager>
</Person>...
</Employees>
新源XML:
<Employees>
<Person>
<FirstName>Joy</FirstName>
<DetailsArray>
<Details1>
<IsManager>N</IsManager>
<IsSuperviser>N</IsSuperviser>
</Details1>
<Details2>
<IsManager>N</IsManager>
<IsSuperviser>N</IsSuperviser>
</Details2>
</DetailsArray>
</Person>
<Person>
<FirstName>Joyce</FirstName>
<DetailsArray>
<Details1>
<IsManager>N</IsManager>
<IsSuperviser>N</IsSuperviser>
</Details1>
<Details2>
<IsManager>N</IsManager>
<IsSuperviser>N</IsSuperviser>
</Details2>
</DetailsArray>
</Person>
<Person>
<FirstName>Joe</FirstName>
<DetailsArray>
<Details1>
<IsManager>N</IsManager>
<IsSuperviser>N</IsSuperviser>
</Details1>
<Details2>
<IsManager>Y</IsManager>
<IsSuperviser>N</IsSuperviser>
</Details2>
</DetailsArray>
</Person>...
</Employees>
输出应该是:
<Names>
<Name num='1'>Joe</Name>
<Name num='2'>Joy</Name>
<Name num='3'>Joyce</Name>
....
</Names>
与以前的XML相比,此源XML有一些调整。这里的新条件是“人可能链接到2个项目或2个任务”,所以我需要输出从IsManager ='Y'的人开始,即使IsManager在DetailsArray的Details2标签中是'y'。输出不应该有名称的重复。假设我们排序名称将被重复..
感谢您以前的答案..
答案 0 :(得分:2)
修改即可。正如lwburk指出的那样,这个答案的原始解决方案只是按IsManager
对节点进行排序。
这是一个解决方案,找到第一个经理,打印出来,然后循环通过剩下的人(如果需要,骑自行车回到开头)。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Employees">
<xsl:variable name="position" select="count(Person) - count(Person/IsManager[. = 'Y'][1]/../following-sibling::*)" />
<xsl:call-template name="person">
<xsl:with-param name="name" select="Person/IsManager[. = 'Y'][1]/../FirstName" />
<xsl:with-param name="position" select="'1'" />
</xsl:call-template>
<xsl:for-each select="Person[position() > $position]">
<xsl:call-template name="person" />
</xsl:for-each>
<xsl:for-each select="Person[position() < $position]">
<xsl:call-template name="person" />
</xsl:for-each>
</xsl:template>
<xsl:template name="person">
<xsl:param name="name" select="FirstName" />
<xsl:param name="position" select="position() + 1" />
<Name>
<xsl:attribute name="num"><xsl:value-of select="$position" /></xsl:attribute>
<xsl:value-of select="$name" />
</Name>
</xsl:template>
</xsl:stylesheet>
旧答案。
我不确定你的问题,但我想你想从IsManager = Y
的人那里得到所有的名字。您可以使用<xsl:sort>
IsManager
值。不要忘记在属性“order”中指定“descending”(否则,IsManager = Y
的人将是最后一个)。
我写了一个与输入数据一起使用的示例:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Employees">
<xsl:for-each select="Person">
<xsl:sort select="IsManager" order="descending" />
<Name>
<xsl:attribute name="num">
<xsl:value-of select="position()" />
</xsl:attribute>
<xsl:value-of select="FirstName" />
</Name>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这个简短而简单的转换(没有模式,没有变量,只有三个模板):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<Names>
<xsl:apply-templates select="*/Person[IsManager='Y'][1]"/>
</Names>
</xsl:template>
<xsl:template match="Person[IsManager='Y']">
<xsl:apply-templates select=
"FirstName |../Person[not(generate-id()=generate-id(current()))]
/FirstName
">
<xsl:sort select=
"generate-id(..) = generate-id(/*/*[IsManager = 'Y'][1])"
order="descending"/>
<xsl:sort select=
"boolean(../preceding-sibling::Person[IsManager='Y'])"
order="descending"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="FirstName">
<Name num="{position()}"><xsl:value-of select="."/></Name>
</xsl:template>
</xsl:stylesheet>
应用于以下XML (与@lwburk提供的相同):
<Employees>
<Person>
<FirstName>Joy</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Joyce</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Joe</FirstName>
<IsManager>Y</IsManager>
</Person>
<Person>
<FirstName>Professor X</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Songey</FirstName>
<IsManager>Y</IsManager>
</Person>
</Employees>
生成想要的正确结果:
<Names>
<Name num="1">Joe</Name>
<Name num="2">Professor X</Name>
<Name num="3">Songey</Name>
<Name num="4">Joy</Name>
<Name num="5">Joyce</Name>
</Names>
解释:
这是使用多个键进行排序的典型案例。
优先级最高的排序标准是Person父级是否是第一个经理。
第二个优先级排序标准是父人是否跟随经理。
我们使用以下事实:在false()
之前排序布尔值true()
时,我们按降序处理排序的节点列表。
答案 2 :(得分:0)
听起来你正试图从第一个管理器开始,然后按顺序处理所有Person
元素,循环回到开头以获取分区元素之前的所有元素。
以下样式表实现了预期的结果:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="Employees/Person"/>
</xsl:template>
<xsl:template match="Person[IsManager='Y'][1]">
<Name num="1">
<xsl:apply-templates select="FirstName"/>
</Name>
<!-- partition -->
<xsl:apply-templates select="following-sibling::Person" mode="after"/>
<xsl:apply-templates select="../Person" mode="before">
<xsl:with-param name="pos" select="last() - position() + 1"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Person" mode="after">
<Name num="{position() + 1}">
<xsl:apply-templates select="FirstName"/>
</Name>
</xsl:template>
<xsl:template match="Person[not(IsManager='Y') and
not(preceding-sibling::Person[IsManager='Y'])]" mode="before">
<xsl:param name="pos" select="0"/>
<Name num="{position() + $pos}">
<xsl:apply-templates select="FirstName"/>
</Name>
</xsl:template>
<xsl:template match="Person"/>
<xsl:template match="Person" mode="before"/>
</xsl:stylesheet>
注意: 1)此解决方案要求源中至少有一个经理; 2)这可能不是一个非常有效的解决方案,因为它需要多次传递并使用preceding-sibling
来测试组成员资格(对于分区元素之前的元素)。
示例输入:
<Employees>
<Person>
<FirstName>Joy</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Joyce</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Joe</FirstName>
<IsManager>Y</IsManager>
</Person>
<Person>
<FirstName>Professor X</FirstName>
<IsManager>N</IsManager>
</Person>
<Person>
<FirstName>Songey</FirstName>
<IsManager>Y</IsManager>
</Person>
</Employees>
输出:
<Name num="1">Joe</Name>
<Name num="2">Professor X</Name>
<Name num="3">Songey</Name>
<Name num="4">Joy</Name>
<Name num="5">Joyce</Name>