2013-05-29 4 views
0

Я выполнил поиск и до сих пор не имею четкого представления.
Я получил XML, который кроме как в моем местном xml.xmlXML XPath игнорировать случай и пробелы

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

Я также попробовать Т Функция ranslate говорит в этом How do i make Xpath search case insensitive, но у меня всегда была ошибка.

+0

Попробуйте установить xml: space = «сохранить» в корневом элементе вашего документа. – Orangepill

+0

@Orangepill, если я это сделаю, это изменит мой весь xml? xml: space = 'preserve' помещает это «sam ple» в «sample»? спасибо за идею сэр. – CaffeineShots

+0

нет, к сожалению, он не разрушит место для вас ... извините – Orangepill

ответ

1

Xpath SimpleXML является не очень подходит для выполнения всей работы. Особенно нечувствительный к регистру поиск довольно неудобен - и вы фактически сталкиваетесь со слишком большим количеством in the related question.

Одним из способов упрощения задания является его разделение. Например. сначала получите список всех интересных элементов/атрибутов, затем отфильтруйте их и затем получите все их родительские элементы.

Это можно легко сделать путем поворота результат 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; 
    } 
} 
+0

отличный код, теперь мое свидание шире. Я обязательно попробую это. – CaffeineShots

+0

Я новичок в кодировании MVC для php, у меня возникла проблема, когда поставить эти классы с тех пор, как у меня есть основной класс, но скоро я исправлю, что буду обновлять вас. Спасибо за большую помощь. – CaffeineShots

+1

Это не связано с MVC, я предлагаю вам создать библиотечную папку, в которую вы можете поместить все свои классы, а затем создать какой-то автозагрузчик. Это обычно довольно легкий вес. – hakre

-1

Если вы хотите, чтобы каждый @name, который начинается, с «образцом», не заботясь о случаях и пространство между ними, вы должны использовать:

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

вывода: все элементы

+0

действительно? включая это <ИМЯ НАЗВАНИЯ = 'Sam Ple lorem ipsum'>? и могу ли я спросить, как это работает [sS] \ s? [aA] \ s? [mM] \ s? [pP] \ s? [lL] \ s? [eE]? Спасибо – CaffeineShots

+0

Да, это позаботится все такое, как «sampl e», «SA m PL e» или какая-либо комбинация. [sS] мы проверяем, что это должен быть любой символ из 's' или 'S' и '\ s?' мы проверяем пространство, которое может или не может присутствовать. –

+0

Я еще больше сэр, вы говорите в вышеприведенном коде, что до тех пор, пока «образец» находится в начале. Что делать, если у меня есть узел, например , каким будет наше лечение? будет ли он задействован в выходе? Большое спасибо! – CaffeineShots

Смежные вопросы