2011-09-07 15 views
5

XMLフィールドの前後にあるすべてのスペース文字を削除するにはどうすればよいですか?XML要素の開始および終了スペースを削除する

<data version="2.0"> 

    <field> 

    1 

    </field>   

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

    2 

    </field> 

</data> 

1と2の前にスペースを入れ、 'some some here here ...'をメモします。これをPHPで削除します。

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

print_r($xml); 

また、データが文字列ではないように見えるため、各変数の前に(文字列)を追加する必要があります。どうして? simplexml_load_file()は、配列にデータを読み込みますので、あなたがこのような何かを行うことができ

+1

http://stackoverflow.com/questions/8200582/remove-newline-from-xml-element-で私の答えを参照してください。 value/8200664#8200664可能な解決策はありません – Gordon

答えて

1

function TrimArray($input){ 

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

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

いいえ、データを配列に読み込まないで、その中から** SimpleXMLElement **を作成します。そして、そのオブジェクトは文字列への大文字小文字にすることができます(これは 'trim'を呼び出したときに起こります)。 – hakre

1

あなたはこのようなものを使用することもできます。私はこれを試していない

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

を、しかし、詳細については、http://www.lonhosford.com/lonblog/2011/01/07/php-simplexml-load-xml-file-preserve-cdata-remove-whitespace-between-nodes-and-return-json/をご覧ください。開閉括弧の間にスペース(<x> _space_ </x>)と属性(<x attr=" _space_ ">)は実際に(<x> _space_ <y>間のスペースとは対照的に)は、XML文書のデータの一部であるので、私はあなたが使用しているソースを示唆していることを

注意スペースを少し乱雑にすべきです。 PHPで最初にあなたがDOMXPathを使うことの最大を経由して適切内の空白を正規化するノードに対応できるようにのDOMDocumentに文書を変換する必要があることを行うには

0

(xpath in)SimpleXMLElementは、この操作に必要とされるほど正確にテキストノードにアクセスするにはあまりにも制限されています。

アンのXPathクエリリーフ要素内にあるすべてのテキスト・ノードとすべての属性にアクセスするには、次のとおりです。

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

$xmlはあなたがのようなホワイトスペースの正規化を行うことができたSimpleXMLElementであることを考えます次の例は:

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

あなたはおそらく、すべてのテキスト・ノード(as suggested in related Q&A)にこれを伸ばすことができ、これは状況下で、文書の正規化が必要な場合があります。 Xpath内のtext()はテキストノードとCdataセクションで異ならないので、これらのタイプのノード(DOMCdataSection)をスキップしたり、ドキュメントをロードするときにテキストノードに展開したりすることができます(the LIBXML_NOCDATA optionを使用)。結果。


またデータは、私は、各変数の前に(文字列)を追加する必要があり、文字列ではありません。どうして?

それはタイプにSimpleXMLElementのオブジェクトなので、あなたがそのようなオブジェクト(要素)の文字列値をしたい場合、あなたはそれを文字列にキャストする必要があります。


そして最後が、少なくともではない:あなたはにSimpleXMLElementにそれを使用する場合print_rまたはvar_dumpを信用していない:それは表示されていないだけでなく、次の参照の質問を参照してください真実。例えば。また、あなたの問題を解決することができ__toString()オーバーライドすることができます:

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

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

print_r($xml); 

文字列にキャストすると、通常(echoで例えば)適用されるにもかかわらずに、print_rの出力は、まだこれらの変更が反映されないでしょう。それで、それに頼らない方がいい、それは決して全体像を示すことはできません。この回答へ


完全なサンプルコード(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(); 
関連する問題