【问题标题】:How can I sort on XML child node value with PHP SimpleDOM? (or any other method)如何使用 PHP SimpleDOM 对 XML 子节点值进行排序? (或任何其他方法)
【发布时间】:2013-01-10 17:02:23
【问题描述】:

我需要根据其子 MajorDescription 的值对以下 XML(foreach ProgramList)进行排序

<ArrayOfProgramList xmlns="http://schemas.datacontract.org/2004/07/Taca.Resources" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ProgramList>
    <AreaOfInterests xmlns:a="http://schemas.datacontract.org/2004/07/Taca">
        <a:AreaOfInterest>
            <a:Interest>ABORIGINAL STUDIES</a:Interest>
        </a:AreaOfInterest>
    </AreaOfInterests>
    <Coop>true</Coop>
    <MajorDescription>ABORIGINAL COMMUNITY AND SOCIAL DEVELOPMENT</MajorDescription>
    <Program>ACSD</Program>
    <ProgramLocations>
        <ProgramLocation>
            <Campus>Barrie</Campus>
        </ProgramLocation>
    </ProgramLocations>
    <Term>201210</Term>
</ProgramList>
<ProgramList>
    <AreaOfInterests xmlns:a="http://schemas.datacontract.org/2004/07/Taca">
        <a:AreaOfInterest>
            <a:Interest>GRADUATE CERTIFICATE STUDIES</a:Interest>
        </a:AreaOfInterest>
        <a:AreaOfInterest>
            <a:Interest>HEALTH AND WELLNESS STUDIES</a:Interest>
        </a:AreaOfInterest>
    </AreaOfInterests>
    <Coop>false</Coop>
    <MajorDescription>ADVANCED CARE PARAMEDIC</MajorDescription>
    <Program>PARM</Program>
    <ProgramLocations>
        <ProgramLocation>
            <Campus>Barrie</Campus>
        </ProgramLocation>
    </ProgramLocations>
    <Term>201210</Term>
</ProgramList>
</ArrayOfProgramList>

我正在尝试使用 SimpleDOM 来完成它,因为我已经阅读了在其他 SO 问题上对 XML 进行排序的最简单方法。

我尝试过使用:

foreach($listxml->sortedXPath('//ArrayOfProgramList/ProgramList','//ArrayOfProgramList/ProgramList/MajorDescription') as $program){ ... }

以及各种其他类似的“排序”值,例如“@MajorDescription”、“/MajorDescription”和“.”正如这里所建议的How does one use SimpleDOM sortedXPath to sort on node value?,但是当我用 var_dump() 检查它时,一切都返回一个空数组

我认为问题是我需要对子节点的值进行排序 - 这可能吗? foreach 需要在 ProgramList 上,因为我需要在每次迭代时输出 ProgramList 中所有子节点的值。

有什么建议吗?我不必使用 SimpleDOM,我对任何有效的方法持开放态度 - 目前我正在迭代 A-Z 数组,并且对于每个字母,迭代 ProgramList,将 MajorDescription 的第一个字母与当前字母进行比较和如果匹配则输出 - 这显然 不是 理想的,只对第一个字母进行排序......

【问题讨论】:

    标签: php xml xpath simplexml simpledom


    【解决方案1】:

    您可以尝试将所有 ProgramList 元素放入一个数组中,并根据自定义函数对其进行排序。代码应如下所示:

    function cmp($a, $b)
    {
      return strcmp($a->MajorDescription[0],$b->MajorDescription[0])
    }
    
    $arr = $listxml->xpath("//ArrayOfProgramList/ProgramList");
    usort($arr,"cmp");
    

    【讨论】:

    【解决方案2】:

    您的原始代码存在两个问题。首先是您的 XML 使用默认命名空间,并且根据设计,XPath 不支持默认命名空间,因此您必须查找命名空间节点(例如 //foo:bar,而不是 //bar)才能找到它们。如果您无法为此命名空间注册前缀(例如,如果您无法修改源 XML),您可以使用通配符 //* 结合与节点的命名空间和/或本地名称匹配的谓词来匹配命名空间节点。

    $nsPredicate = '[namespace-uri() = "http://schemas.datacontract.org/2004/07/Taca.Resources"]';
    
    $query = '//*[local-name() = "ArrayOfProgramList"]' . $nsPredicate
           . '/*[local-name() = "ProgramList"]' . $nsPredicate;
    
    $orderBy = '*[local-name() = "MajorDescription"]' . $nsPredicate;
    
    foreach ($listxml->sortedXPath($query, $orderBy) as $program)
    {
        echo $program->asXML(),"\n";
    }
    

    另一个问题是您的排序标准。它应该从目标节点的上下文中写入。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 2013-08-30
      • 2020-08-14
      • 2018-11-28
      • 1970-01-01
      相关资源
      最近更新 更多