0

私は検索を行いましたが、これについてはまだ明確な見解がありません。
ローカルの xml.xml に保存されている XML を取得しました

<ITEM NAME='Sample'>
   ..some other node here
</ITEM >
<ITEM NAME='SamPlE lorem'>
   ..some other node here
</ITEM >
<ITEM  NAME='Sam Ple lorem ipsum'>
   ..some other node here
</ITEM >
<ITEM  NAME='sample'>
   ..some other node here
</ITEM >
<ITEM  NAME='SAMPLE'>
   ..some other node here
</ITEM >

$xmlfile = 'localhost/project/xml.xml'
$xml = simplexml_load_file($xmlfile);

上記のxmlのすべてのノードにアクセス"sample"できるように、大文字と小文字の区別と空白を無視してこの文字列を検索する必要があります。これまでのところ、これだけですTRUE

 //ITEM is not a parent node thats why I am using this line 
 //to lead me to certain part of my xml
 //that match my contain search

 $string = "sample";
 $result = $xml->xpath("//ITEM[contains(@NAME, '$string')");

しかし、私はの結果を得ました

<ITEM  NAME='sample'>
   ..some other node here
</ITEM >

また、このHow do i make Xpath search case insensitiveで説明されている翻訳機能も試してみましたが、常にエラーが発生しました。

4

2 に答える 2

1

SimpleXML の Xpath は、すべての作業を行うにはあまり適していません。特に、大文字と小文字を区別しない検索はかなり厄介です。関連する質問では、実際にはあまりにも多くのことに直面しています。

仕事を単純化する 1 つの方法は、仕事を分割することです。たとえば、最初にすべての興味深い要素/属性のリストを取得し、次にそれらをフィルタリングしてから、すべての親要素を取得します。

これは、xpath の結果 (配列) をIterator

$string   = "sample";
$names    = $xml->xpath('//ITEM/@NAME');
$filtered = new LaxStringFilterIterator($names, $string);
$items    = new SimpleXMLParentNodesIterator($filtered);

foreach ($items as $item) {
    echo $item->asXML(), "\n";
}

これにより、検索されたノードが出力されます (例):

<ITEM NAME="Sample">
   ..some other node here
</ITEM>
<ITEM NAME="SamPlE lorem">
   ..some other node here
</ITEM>
<ITEM NAME="Sam Ple lorem ipsum">
   ..some other node here
</ITEM>
<ITEM NAME="sample">
   ..some other node here
</ITEM>
<ITEM NAME="SAMPLE">
   ..some other node here
</ITEM>

文字列値に基づいて配列をフィルタリングするための別のソリューション:

/**
 * Class LaxStringFilterIterator
 *
 * Search for needle in case-insensitive manner on a subject
 * with spaces removed.
 */
class LaxStringFilterIterator extends FilterIterator
{
    private $quoted;

    /**
     * @param Traversable|Array|Object $it
     * @param string $needle
     */
    public function __construct($it, $needle) {
        parent::__construct($it instanceof Traversable ? new IteratorIterator($it) : new ArrayIterator($it));
        $this->quoted = preg_quote($needle);
    }

    public function accept() {
        $pattern = sprintf('/%s/i', $this->quoted);
        $subject = preg_replace('/\s+/', '', trim(parent::current()));
        return preg_match($pattern, $subject);
    }
}

親ノードのデコレータ:

/**
 * Class SimpleXMLParentNodesIterator
 *
 * Return parent nodes instead of current SimpleXMLElement Nodes,
 * for example the element of an attribute.
 */
class SimpleXMLParentNodesIterator extends IteratorIterator
{
    public function current() {
        $current = parent::current();
        list($parent) = $current[0]->xpath('..');
        return $parent;
    }
}
于 2013-05-29T09:06:14.553 に答える