2011-09-07 33 views
5

Làm cách nào để xóa tất cả ký tự khoảng cách trước và sau một trường XML?Xóa không gian bắt đầu và kết thúc khỏi các phần tử XML

<data version="2.0"> 

    <field> 

    1 

    </field>   

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

    2 

    </field> 

</data> 

Lưu ý rằng khoảng cách trước 1 và 2 và 'một số thuộc tính ở đây ...', tôi muốn loại bỏ điều đó bằng PHP.

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

print_r($xml); 

Ngoài ra dữ liệu không xuất hiện là chuỗi, tôi cần nối thêm (chuỗi) trước mỗi biến. Tại sao?

+1

xin vui lòng xem câu trả lời của tôi tại http://stackoverflow.com/questions/8200582/remove-newline-from-xml-element- value/8200664 # 8200664 cho một giải pháp có thể – Gordon

Trả lời

1

Kể từ simplexml_load_file() đọc dữ liệu vào một mảng, bạn có thể làm một cái gì đó như thế này:

function TrimArray($input){ 

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

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

Không, nó không đọc dữ liệu vào một mảng, nhưng nó tạo ra một ** SimpleXMLElement ** ra khỏi nó. Và đối tượng đó có thể là trường hợp thành chuỗi (đó là những gì sẽ xảy ra khi bạn gọi 'trim' trên nó). – hakre

1

Bạn có thể muốn sử dụng một cái gì đó như thế này:

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

tôi đã không cố gắng này, nhưng bạn có thể tìm hiểu thêm về điều này tại http://www.lonhosford.com/lonblog/2011/01/07/php-simplexml-load-xml-file-preserve-cdata-remove-whitespace-between-nodes-and-return-json/.

Lưu ý rằng khoảng cách giữa dấu ngoặc mở và đóng (<x> _space_ </x>) và thuộc tính (<x attr=" _space_ ">) thực sự là một phần của dữ liệu của tài liệu XML (trái ngược với khoảng cách giữa <x> _space_ <y>), vì vậy tôi sẽ đề xuất nguồn bạn sử dụng nên có chút lộn xộn hơn với không gian.

0

Để làm điều đó trong PHP trước tiên bạn phải chuyển đổi các tài liệu vào một DOMDocument để bạn có thể giải quyết các nút bạn muốn bình thường hóa các khoảng trắng trong vòng đúng qua DOMXPath. (Xpath in) SimpleXMLElement quá giới hạn để truy cập các nút văn bản đủ chính xác vì nó cần thiết cho thao tác này.

XPath truy vấn để truy cập tất cả các văn bản nút đó nằm trong lá yếu tố và tất cả các thuộc tính là:

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

Cho rằng $xml là một SimpleXMLElement bạn có thể làm trắng-không gian bình thường như trong ví dụ sau:

$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), ' '); 
} 

Bạn có thể kéo dài điều này đến tất cả các nút văn bản (as suggested in related Q&A), nhưng điều này có thể yêu cầu chuẩn hóa tài liệu trong hoàn cảnh. Vì text() trong Xpath không khác nhau giữa các nút văn bản và phần Cdata, bạn có thể muốn bỏ qua các loại nút này (DOMCdataSection) hoặc mở rộng chúng thành các nút văn bản khi tải tài liệu (sử dụng the LIBXML_NOCDATA option cho điều đó) để đạt được hữu ích hơn các kết quả.


Ngoài ra các dữ liệu không xuất hiện để được chuỗi, tôi cần phải thêm (string) trước mỗi biến. Tại sao?

Bởi vì nó là một đối tượng kiểu SimpleXMLElement, nếu bạn muốn chuỗi giá trị của một đối tượng (element) như vậy, bạn cần phải cast nó vào chuỗi.Xem cũng như các câu hỏi tham khảo sau đây:


Và cuối cùng nhưng không kém phần quan: không tin tưởng print_r hoặc var_dump khi bạn sử dụng nó trên một SimpleXMLElement: nó không hiển thị sự thật. Ví dụ. bạn có thể ghi đè lên __toString() mà cũng có thể giải quyết vấn đề của bạn:

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

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

print_r($xml); 

Mặc dù đúc đến chuỗi thông thường sẽ áp dụng (ví dụ: với echo), đầu ra của print_r vẫn sẽ không phản ánh những thay đổi này. Vì vậy, tốt hơn không dựa vào nó, nó không bao giờ có thể hiển thị toàn bộ hình ảnh.


Full mã ví dụ cho câu trả lời này (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(); 
Các vấn đề liên quan