Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 唯一排序节点之前的XSL计数_Xml_Sorting_Xslt_Xpath - Fatal编程技术网

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

Xml 唯一排序节点之前的XSL计数,xml,sorting,xslt,xpath,Xml,Sorting,Xslt,Xpath,我有一个相当复杂的XSL任务。我有一个XML文档,看起来像 <authorlist> <orgs> <org id="org1" name="Org A"/> <org id="org2" name="Org B"/> <org id="org3" name="Org C"/> </orgs> <authors> <au

我有一个相当复杂的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>
也就是说,作者按姓名的字母顺序排列。每一位作者的名字都会打印出来,并附上上标以表明其所属机构。这些组织将按照它们首次出现在已排序的作者列表中的顺序进行打印。每个作者可能有多个从属关系

以下是我认为我需要做的:

  • 创建一个从组织映射到序号的键,这样我就可以对组织进行正确排序(并在作者姓名上添加正确的上标)。我相信我知道怎么做
  • 要创建该密钥,我需要计算与当前(创建密钥时)组织关联的作者的第一个实例之前的唯一作者关联的数量。我想我知道怎么做
  • 踢球者是如何定义“先发”和“先发”的。如果我理解正确,“previous”和“first”是由文档顺序定义的,或者可能是由一些模糊的XPath“processing order”定义的。我迫切需要通过按姓名字母顺序对作者进行排序来定义“之前”和“第一”。我不知道怎么做,甚至不知道这是否可能
  • 我可以使用的XSLT处理器是xsltproc,它实现XSLT1.0。如果有足够令人信服的案例,我可以考虑使用不同的处理器,但我是否能够使用不同的处理器有些疑问

    现实世界的情况变得更加复杂,因为有些组织有多个子组织,还有两类组织,成员组织和访客组织,它们被打印在单独的列表中,并且它们的上标有独立的顺序。但是,我认为解决上述问题就足以解决其余问题。

    一种方法:

    <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} A.托尔^{1} B.托尔^{2} C.托尔^{1,3} 这种方法基于以正确的顺序(即,按字母名称顺序由
    auth
    和按文档顺序在
    auth
    中)构建一个分隔字符串
    affil/@id

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

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


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

    您能否解释
    A.Thor^{1}
    是如何结合在一起的?
    1
    代表什么,我不太清楚。(我猜它指的是
    org3
    ,因为如果你按姓名对作者进行排序,那将是第一个组织。对吗?)A.托尔与org3(orgC)有关联。由于A.Thor是第一位(按字母顺序排列)作者,而org3是A.Thor的第一个附属机构,所以org3得到索引1。所以,我们有A.Thor^{1},表明A.Thor与索引为1的组织有关联,这是OrgC。这非常令人困惑,这可能就是我为什么要与它斗争的原因。OrgC是如何得到索引1的?你的例子中没有任何东西暗示这一点。还有,到目前为止你试过什么?请发布你现有的作品,并解释为什么它不能满足你的需要。因为它是第一作者的第一个附属机构,所以OrgC会有索引1。正如我在原文中所说,“组织是按照它们第一次出现在作者排序列表中的顺序打印的。”我应该更清楚地说,“组织是按照它们第一次出现在作者排序列表中的顺序编制索引的,它们是按照索引的顺序打印的。”这很难看,但它是有效的,所以我不在乎它有多难看。需要做一个更改:xsl:sort需要一个额外的属性data type=“number”。很可能对于这个特定的问题没有真正漂亮的解决方案。这有一个问题,即如果字符串
    $orgIndex
    '| org3 | org3 | org1 | org2 | org3'
    ,那么
    'org1'
    将被赋予索引3和
    'org2'
    索引4。我的真实世界作者列表有大约60个组织和400人,组织索引最多有488个!我正在努力找到解决办法。此外,有些组织的
    id
    是另一个组织的
    id
    的子字符串(例如
    'org1'
    'org10'
    )。不过,我认为解决方案很简单,只需在
    id
    的适当末尾添加一个分隔符即可。 A. Thor ^{1} B. Thor ^{2} C. Thor ^{1,3}