gpt4 book ai didi

xml - 唯一排序节点之前的 XSL 计数

转载 作者:数据小太阳 更新时间:2023-10-29 02:40:57 25 4
gpt4 key购买 nike

我有一个相当复杂的 XSL 任务。我有一个 XML 文档,看起来像

<authorlist>
<orgs>
<org id="org1" name="Org A"/>
<org id="org2" name="Org B"/>
<org id="org3" name="Org C"/>
</orgs>
<authors>
<auth name="C. Thor">
<affiliations>
<affil id="org2"/>
<affil id="org3"/>
</affiliations>
</auth>
<auth name="A. Thor">
<affiliations>
<affil id="org3"/>
</affiliations>
</auth>
<auth name="B. Thor">
<affiliations>
<affil id="org1"/>
</affiliations>
</auth>
</authors>
</authorlist>

我想编写一个 XSL 转换来生成以下(文本)输出

1 Org C
2 Org A
3 Org B

A. Thor ^{1}
B. Thor ^{2}
C. Thor ^{1,3}

也就是说,作者按姓名字母顺序排序。每个作者的名字都被打印出来,连同表明她的隶属关系的上标。这些组织按照它们首次出现在排序的作者列表中的顺序打印。每个作者可能有多个隶属关系。

这是我认为我需要做的:

  1. 创建一个从组织映射到序号的键,这样我就可以正确地对组织进行排序(并将正确的上标放在作者姓名上)。我相信我知道该怎么做。
  2. 要创建该 key ,我需要计算隶属于当前(创建 key 时)组织的作者的第一个实例之前的唯一作者隶属关系的数量。我想我知道该怎么做。
  3. 关键在于“preceding”和“first”的定义方式。如果我理解正确的话,“preceding”和“first”是由文档顺序定义的,或者可能是由一些模糊的 XPath“处理顺序”定义的。我迫切需要通过按姓名字母顺序对作者进行排序来定义“在先”和“首先”。我不知道该怎么做,甚至不知道是否可行。

我可以使用的 XSLT 处理器是 xsltproc,它实现了 XSLT 1.0。如果有足够令人信服的案例,我可以考虑提供不同的处理器,但我是否能够使用不同的处理器有点值得怀疑。

实际情况比较复杂,因为有组织有多个子组织,还有两类组织,成员(member)组织和访客组织,它们分别打印在单独的列表中,并且有独立的顺序他们的上标。但是,我认为解决上述问题就足以完成剩下的工作。

最佳答案

一种方法:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />

<xsl:variable name="orgIndex">
<xsl:apply-templates select="//authors/auth" mode="orgIdx">
<xsl:sort select="@name" />
</xsl:apply-templates>
</xsl:variable>

<xsl:template match="authorlist">
<xsl:apply-templates select="authors" />
</xsl:template>

<xsl:template match="authors">
<xsl:apply-templates select="auth">
<xsl:sort select="@name" />
</xsl:apply-templates>
</xsl:template>

<xsl:template match="auth">
<xsl:value-of select="@name" />
<xsl:text> ^{</xsl:text>
<xsl:apply-templates select="affiliations/affil" mode="orgIdx">
<xsl:sort select="string-length(substring-before($orgIndex, @id))" data-type="number" />
</xsl:apply-templates>
<xsl:text>}</xsl:text>
<xsl:if test="position() &lt; last()">
<xsl:value-of select="'&#xA;'" />
</xsl:if>
</xsl:template>

<xsl:template match="affil" mode="orgIdx">
<xsl:variable name="str" select="substring-before($orgIndex, @id)" />
<xsl:variable name="idx" select="string-length($str) - string-length(translate($str, '|', ''))" />
<xsl:value-of select="$idx" />
<xsl:if test="position() &lt; last()">,</xsl:if>
</xsl:template>

<xsl:template match="auth" mode="orgIdx">
<xsl:for-each select="affiliations/affil">
<xsl:value-of select="concat('|', @id)" />
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

结果

A. Thor ^{1}B. Thor ^{2}C. Thor ^{1,3}

这种方法是基于以正确的顺序构建一个分隔字符串 affil/@id(即,通过 auth 按字母名称顺序,并在 auth 按文档顺序)。

对于您的示例,字符串 $orgIndex 将为 '|org3|org1|org2|org3'

@id 将在该字符串中重复,但这没关系,因为我们不关心字符串的后部。

现在我们可以使用 substring-before() 来确定 ID 第一次出现之前的定界字符数,这会导致您似乎正在寻找的数字索引。

关于xml - 唯一排序节点之前的 XSL 计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20131695/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com