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