2017-05-26 8 views
1

私は外部のベンダーにXML文書を送信していますが、そのうちの1つはXMLコンテンツの中に一重引用符と二重引用符があるため、XMLの解析に問題があります。公式のXML仕様では、属性で使用するとエスケープする必要があるだけですが、PHPのSimpleXMLElementを拡張して引用符をエスケープするのはあまり難しくないと思いました。これはそうではありませんでした。PHPのSimpleXMLElementを拡張する

<?php 
class BetterXMLElement extends SimpleXMLElement 
{ 
    public function __set($name, $value) 
    { 
     echo "called __set with $name and $value"; 
     $this->addChild($name, $value); 
    } 

    public function addChild($name, $value=null, $ns=null) 
    { 
     $new_value = strtr($value, [ 
      '&' => '&amp;', 
      '"' => '&quot;', 
      "'" => '&apos;', 
     ]); 
     echo "New Value: $new_value\n"; 
     parent::addChild($name, $new_value, $ns); 
    } 
} 

$xml = new BetterXMLElement('<?xml version="1.0" encoding="UTF-8"?><TRANSACTION></TRANSACTION>'); 
$xml->COST = "apos: ', amp: &, quot: \""; 
$xml->addChild('PRODUCT', "apos: ', amp: &, quot: \""); 
echo $xml->asXML(); 

上記のコードの出力:これは私に示して何

New Value: apos: &apos;, amp: &amp;, quot: &quot; 
<?xml version="1.0" encoding="UTF-8"?> 
<TRANSACTION><COST>apos: ', amp: &amp;, quot: "</COST><PRODUCT>apos: ', amp: &amp;, quot: "</PRODUCT></TRANSACTION> 

は次のとおりです。

  1. 私と同じように__setでエコーが、呼び出されていない私の最初の試みは、このました私がCOSTを設定しているときであることを期待してください。なぜこれは機能しないのですか?
  2. PRODUCTを設定すると、addChildのオーバーライドが呼び出されていますが、asXMLが呼び出されると、引用符のHTMLエンティティが変換されて戻ってきます。なぜそれはこのように機能するのですか?それを無効にする方法はありますか?
+0

問題を再現する方法を示すコードサンプルが参考になります。 –

+0

@JakubMatczak良い点、私はいくつかの使用例と出力を追加しました! –

+0

'SimpleXMLElement'クラスは通常のクラスではありません。それはクラスのように見えますが、それは規則的ではない方法で多くのことを行います。代わりに 'DOMDocument'を使うことをお勧めします。これは、['loadXML()'](http://php.net/manual/en/domdocument.loadxml.php)と['saveXML()'](http://php.net/manual/en/)を提供します。 domdocument.savexml.php)を使用して、ドキュメントをXMLテキストとしてシリアル化し、その内容を検査および変更するための多くのメソッドを使用できます。 – axiac

答えて

0

私の知る限り、私は原因固有ににSimpleXMLElementかのDOMDocumentのいずれかで行うために必要なものを行うにはきれいな組み込みの方法はありませんlibxml2の設計。 XML処理(たとえば、一重引用符が「{{}}」に置き換えられた)の前に、必要な文字をプレースホルダに置き換え、XML出力の適切なHTMLエンティティでこれらのプレースホルダを交換しました。

また、前のコメントで指摘されているように、SimpleXMLElementは通常のPHPクラスではありません。そのため、オーバーライドが失敗したのです。

0

シンプルなxmlを使用しないでください - それはごみです!

代わりにDOMDocument()を試してください!

次のものを作成します
$dom = new DOMDocument(); 
$hello = $dom->createElement('hello'); 
$hello->setAttribute('such', 'wow'); 
$text = new DOMText('This & That'); 
$hello->appendChild($text); 
$dom->appendChild($hello); 
echo $dom->saveXML(); 

<?xml version="1.0"?> <hello such="wow">This &amp; That</hello>