【问题标题】:How to sort xml child via attribute value PhP如何通过属性值 PhP 对 xml 子项进行排序
【发布时间】:2020-09-07 13:02:24
【问题描述】:

我有一个通过 PHP 的 XML 文件,我试图根据属性“word”在 div 中按升序列出特定的子“word”。

我把 sort($word);没有成功

这是我的代码:

<?php
if(isset($_POST['submitSave'])) {
// Disable errors due to empty xml files
error_reporting(E_ALL & ~E_WARNING);

$domDoc = new DOMDocument('1.0');
$domDoc->preserveWhiteSpace = false;
$domDoc->formatOutput = true;
$xpath = new DOMXpath($domDoc);

// load xml file
try {
    $domDoc->load('./data/expression.xml');
} catch (\Throwable $th) {
    //throw $th;
}

if($domDoc->getElementsByTagName('expression')->length>0){
    // If we already have expression tag defined
    $expression = $domDoc->getElementsByTagName('expression')[0];
}else{
    // If we don't have any expression tag, i.e. file is empty
    $expression = $domDoc->createElement('expression');
}



  // Create child node for product and set id(attribute), word(child), 
  meaning(child)
$vocabulario = $domDoc->createElement('vocabulario');
$vocabulario->setAttribute('word', $_POST['word']);
$word = $domDoc->createElement('word', $_POST['word']);
$meaning = $domDoc->createElement('meaning', $_POST['meaning']);




$domDoc->appendChild($expression);
$expression->appendChild($vocabulario);
$vocabulario->appendChild($word);
$vocabulario->appendChild($meaning);



// convert returned node list into an array
$vocabularios = iterator_to_array(
// fetch all vocabulario elements
$xpath->evaluate('/expression/vocabulario')  
);
// sort the array
usort(
$vocabularios,
static function($a, $b) use ($xpath) {
    // compare the word child element
    return strcasecmp(
        $xpath->evaluate('string(word)', $a),
        $xpath->evaluate('string(word)', $b)
       );
      }
    );

// iterate the sorted array
foreach ($vocabularios as $vocabulario) {
// append node to the expression document element
// that moves nodes from their current position
$domDoc->documentElement->appendChild($vocabulario);
}




file_put_contents('./data/expression.xml', $domDoc->saveXML());

}
?>

输出

    <?xml version="1.0" encoding="UTF-8"?>
<expression>
  <vocabulario word="piece">
    <word>piece</word>
    <meaning>pedaço</meaning>
  </vocabulario>
  <vocabulario word="ball">
    <word>ball</word>
    <meaning>bola</meaning>
  </vocabulario>
</expression>

所以,单词“ball”应该列在“piece”之前,正如我在上面解析 php 页面中的 xml 时所说的升序。

【问题讨论】:

  • 请使用expression.xml 的代表性样本和您的预期输出来编辑您的问题。
  • @JackFleeting 好的
  • DOMXpath 实例需要在加载 XML 之后创建。此外,您不应使用 getElementsByTagName() - expression 是文档元素。只需检查它是否是具有预期名称的 DOMElement 的实例。

标签: php xml listview domdocument


【解决方案1】:

SimpleXML 不擅长处理节点,因此使用 DOM 会容易得多。

$document = new DOMDocument();
$document->preserveWhiteSpace = FALSE;
$document->loadXML($xmlString);
$xpath = new DOMXpath($document);

// convert returned node list into an array
$vocabularios = iterator_to_array(
    // fetch all vocabulario elements
    $xpath->evaluate('/expression/vocabulario')  
);
// sort the array
usort(
    $vocabularios,
    static function($a, $b) {
        // compare the word attribute
        return strcasecmp($a->getAttribute('word'), $b->getAttribute('word'));
    }
);

// iterate the sorted array
foreach ($vocabularios as $vocabulario) {
    // append node to the expression document element
    // that moves nodes from their current position
    $document->documentElement->appendChild($vocabulario);
}

$document->formatOutput = TRUE;
echo $document->saveXML();

要按子元素文本内容排序,您只需更改比较功能。

usort(
    $vocabularios,
    static function($a, $b) use ($xpath) {
        // compare the word child element
        return strcasecmp(
            $xpath->evaluate('string(word)', $a),
            $xpath->evaluate('string(word)', $b)
        );
    }
);

【讨论】:

  • 我更新了上面的代码。如您所见,我尝试按照您的指示进行操作,但没有成功。我认为缺少某些东西或者我做错了。你能帮帮我吗?
猜你喜欢
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多