2011-09-07 15 views
5

Jak usunąć wszystkie znaki odstępu przed i za polem XML?Usuwanie początkowych i końcowych spacji z elementów XML

<data version="2.0"> 

    <field> 

    1 

    </field>   

    <field something=" some attribute here... "> 

    2 

    </field> 

</data> 

Zauważ, że odstępy przed 1 i 2 oraz "jakiś atrybut tutaj ...", chcę usunąć to z PHP.

if(($xml = simplexml_load_file($file)) === false) die(); 

print_r($xml); 

Również dane nie wydają się być ciągiem, muszę dodać (ciąg) przed każdą zmienną. Czemu?

+1

zobacz moją odpowiedź na http://stackoverflow.com/questions/8200582/remove-newline-from-xml-element- value/8200664 # 8200664 dla możliwego rozwiązania – Gordon

Odpowiedz

1

Od simplexml_load_file() odczytuje dane do tablicy, można zrobić coś takiego:

function TrimArray($input){ 

    if (!is_array($input)) 
     return trim($input); 

    return array_map('TrimArray', $input); 
} 
+0

Nie, nie odczytuje danych do tablicy, ale tworzy z niej ** SimpleXMLElement **. I ten obiekt może być sprowadzony do łańcucha znaków (co dzieje się, gdy wywołasz na nim "trim"). – hakre

1

Możesz użyć czegoś takiego:

$str = file_get_contents($file); 
$str = preg_replace('~\s*(<([^>]*)>[^<]*</\2>|<[^>]*>)\s*~','$1',$str); 
$xml = simplexml_load_string($xml,'SimpleXMLElement', LIBXML_NOCDATA); 

nie próbowałem tego, ale Więcej informacji na ten temat można znaleźć pod adresem http://www.lonhosford.com/lonblog/2011/01/07/php-simplexml-load-xml-file-preserve-cdata-remove-whitespace-between-nodes-and-return-json/.

Zauważmy, że przestrzenie między otwarciem i nawiasów zamykających (<x> _space_ </x>) oraz atrybutów (<x attr=" _space_ ">) są rzeczywiście część danych dokumentu XML (w przeciwieństwie do przestrzeni między <x> _space_ <y>), więc sugeruję, że źródłem użyć powinien być nieco mniej brudny ze spacjami.

0

Aby to zrobić w PHP musisz najpierw przekonwertować dokument w DOMDocument tak, że można zająć się węzły, które chcesz normalizować białe znaki w prawidłowo poprzez DOMXPath. (Xpath in) SimpleXMLElement jest zbyt ograniczony, aby uzyskać dostęp do węzłów tekstowych na tyle precyzyjnie, jak byłby potrzebny w tej operacji.

XPath-query dostęp do wszystkich tekstowych węzły, które są w zasięgu liści elementów i wszystkie atrybuty to:

//*[not(*)]/text() | //@* 

Zważywszy, że $xml jest SimpleXMLElement można zrobić white-space normalizację jak w Poniższy przykład:

$doc = dom_import_simplexml($xml)->ownerDocument; 
$xpath = new DOMXPath($doc); 
foreach ($xpath->query('//*[not(*)]/text()|//@*') as $node) { 
    /** @var $node DOMText|DOMAttr */ 
    $node->nodeValue = trim(preg_replace('~\s+~u', ' ', $node->nodeValue), ' '); 
} 

można to może rozciągnąć na wszystkie węzły tekstowe (as suggested in related Q&A), ale może to wymagać dokumentów normalizację pod okoliczności. Ponieważ text() w Xpath nie różni się między węzłami tekstowymi i Cdata, możesz pominąć te typy węzłów (DOMCdataSection) lub rozwinąć je do węzłów tekstowych podczas ładowania dokumentu (użyj do tego celu the LIBXML_NOCDATA option), aby uzyskać bardziej przydatne wyniki.


również nie wydaje się być dane ciąg, muszę dołączyć (string) przed każdą zmienną. Czemu?

Bo to obiekt typu SimpleXMLElement, jeśli chcesz wartość ciągu takiego obiektu (element), trzeba oddać go do łańcucha.Patrz także następujące pytanie Numer referencyjny:


I last but not least: nie ufaj print_r lub var_dump podczas używania go na SimpleXMLElement: to nie wykazujące prawda. Na przykład. można zastąpić __toString() który może również rozwiązać problem:

class TrimXMLElement extends SimpleXMLElement 
{ 
    public function __toString() 
    { 
     return trim(preg_replace('~\s+~u', ' ', parent::__toString()), ' '); 
    } 
} 

$xml = simplexml_load_string($buffer, 'TrimXMLElement'); 

print_r($xml); 

Nawet odlewania ciąg normalnie stosuje się (na przykład z echo), wyjście print_r nadal nie odzwierciedlać te zmiany. Lepiej nie polegać na tym, nigdy nie może pokazać całego obrazu.


Pełny przykład kodu do tej odpowiedzi (Online Demo):

<?php 
/** 
* Remove starting and ending spaces from XML elements 
* 
* @link https://stackoverflow.com/a/31793566/367456 
*/ 

$buffer = <<<XML 
<data version="2.0"> 

    <field> 

    1 

    </field> 

    <field something=" some attribute here... "> 

    2 <![CDATA[ 34 ]]> 

    </field> 

</data> 
XML; 

class TrimXMLElement extends SimpleXMLElement implements JsonSerializable 
{ 
    public function __toString() 
    { 
     return trim(preg_replace('~\s+~u', ' ', parent::__toString()), ' '); 
    } 

    function jsonSerialize() 
    { 
     $array = (array) $this; 

     array_walk_recursive($array, function(&$value) { 
      if (is_string($value)) { 
       $value = trim(preg_replace('~\s+~u', ' ', $value), ' '); 
      } 
     }); 

     return $array; 
    } 
} 

$xml = simplexml_load_string($buffer, 'TrimXMLElement', LIBXML_NOCDATA); 

print_r($xml); 
echo json_encode($xml); 

$xml = simplexml_load_string($buffer, null, LIBXML_NOCDATA); 

$doc = dom_import_simplexml($xml)->ownerDocument; 
$doc->normalizeDocument(); 
$doc->normalize(); 

$xpath = new DOMXPath($doc); 
foreach ($xpath->query('//*[not(*)]/text()|//@*') as $node) { 
    /** @var $node DOMText|DOMAttr|DOMCdataSection */ 
    if ($node instanceof DOMCdataSection) { 
     continue; 
    } 
    $node->nodeValue = trim(preg_replace('~\s+~u', ' ', $node->nodeValue), ' '); 
} 

echo $xml->asXML(); 
Powiązane problemy