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);

我需要搜索此字符串"sample",忽略区分大小写和空格,以便我可以TRUE访问上述 xml 的每个节点,到目前为止我只有这个

 //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 >

我还尝试了如何使 Xpath 搜索不区分大小写中所说的翻译功能,但我总是遇到错误。

4

2 回答 2

1

SimpleXML 的 Xpath 不太适合完成整个工作。尤其是不区分大小写的搜索非常尴尬-实际上您在相关问题中遇到了太多问题

简化工作的一种方法是将其划分。例如,首先获取所有有趣元素/属性的列表,然后过滤它们,然后获取它们的所有父元素。

这可以通过将 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 回答
-1

如果您想获取每个以 'sample' 开头的 @Name 而不考虑大小写和空格,则必须使用:

//ITEM[matches(normalize-space(@NAME), '^[sS]\s?[aA]\s?[mM]\s?[pP]\s?[lL]\s?[eE]')]

输出:所有项目

于 2013-05-29T05:03:48.927 回答