2017-07-01 22 views
2

私は何かを達成しようとしています。SOAP Envelopeの複数のネームスペース属性

<s:Envelope 
xmlns:s="http://www.w3.org/2003/05/soap-envelope" 
xmlns:a="http://www.w3.org/2005/08/addressing" 
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 

と私の最も近い失敗した試みは、次のとおりです:これが私の目標です

提供
$envelope = $this->doc->createElementNS('http://www.w3.org/2003/05/soap-envelope', 's:Envelope'); 
$envelope->setAttributeNS('http://www.w3.org/2003/05/soap-envelope', 'xmlns:u', 'http://www.w3.org/2005/08/addressing'); 
$envelope->setAttributeNS('http://www.w3.org/2003/05/soap-envelope', 'xmlns:u', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'); 

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" 
s:a="http://www.w3.org/2005/08/addressing" 
s:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 

を私は特に、パラメータ1で、パラメータの組み合わせの数十を試してみました'http://www.w3.org/2000/xmlns/'を含むsetAttributeNSの名前空間エラーが発生するか、無視されます。

難しくないはずです...

答えて

0

「単純」を定義してください:)。 XMLネームスペースがあり、特に予約属性( "xmlns"のような "xml"で始まる属性)を作成し、それらの値を設定する必要があります。

ここではいくつかのことが衝突します。まず最初にDOMDocumentがあなたのネームスペースを管理します。 XMLの名前空間には、まずURI(名前空間名)があります。これは通常、URLのように見える識別子です。 "http://www.w3.org/2003/05/soap-envelope"または "http://www.w3.org/2005/08/addressing"。各ノードにその名前空間URIの接頭辞が常に付いている場合、ドキュメントのサイズが大きくなるので、各名前空間URIを短い表現、名前空間接頭辞(たとえば、「s:Envelope」の「s」)にマッピングする方法があります。

ちょうどSOAPエンベロープの要素を見てみましょう:

<{http://www.w3.org/2003/05/soap-envelope}Envelope /> 

代わりにその封筒の要素をこのように書くの、のように行われます:envelope要素がhttp://www.w3.org/2003/05/soap-envelope名前空間にあることを意味している

<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope" /> 

"xmlns"という名前の属性は、名前が "xml"で始まるため予約されています。これは特別な意味を持ち、名前空間名 "http://www.w3.org/XML/1998/namespace"に暗黙的または明示的に拘束されています。この例では、それが属する要素の名前空間、ここではenvelope要素を設定します。

同じ文書内に複数の名前空間を持ち、各ノード(要素など)で完全なURIを繰り返したくない場合は、プレフィックスを定義して代わりにプレフィックスを使用することもできます。

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" /> 

のは、プレーンなPHPコードでそれを見てみましょう:

$doc = new DOMDocument(); 
$envelope = $doc->createElementNS('http://www.w3.org/2003/05/soap-envelope', 'Envelope'); 
$doc->appendChild($envelope); 

これは 『という名前の要素を作成するには、名前空間名」http://www.w3.org/2003/05/soap-envelope』にあなたはすでに、あなたは接頭辞を設定しないものを「s」でありますhttp://www.w3.org/2003/05/soap-envelope「「名前空間名を持つ」Envelope

<?xml version="1.0"?> 
<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope"/> 

あなたはまた、どのを制御したいと名前空間接頭辞は(ここでは「s」)は、その名前空間に使用する(すでに自分で見出したとして)、あなたは同様にそれを追加することができます。

次のXMLで結果の
$doc = new DOMDocument(); 
$envelope = $doc->createElementNS('http://www.w3.org/2003/05/soap-envelope', 's:Envelope'); 
$doc->appendChild($envelope); 

<?xml version="1.0"?> 
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"/> 

次に追加する属性(例: "xmlns:a")が再び予約されます( "xml"で始まる)。

$envelope->setAttributeNS('http://www.w3.org/2003/05/soap-envelope', 'xmlns:a', 'http://www.w3.org/2005/08/addressing'); 

それはあなたが達成したい結果を作成しません:あなたはそれが好きで追加しようとした結果のXMLが示すように

<?xml version="1.0"?> 
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" s:a="http://www.w3.org/2005/08/addressing"/> 

とコードによく見にと、おそらく今以上です名前空間名が「http://www.w3.org/2003/05/soap-envelope」(最初のパラメータがsetAttributeNS)という属性を追加したくないことは明らかです。代わりに、その属性名( "xmlns:a")が "xml"で始まり、予約されている(予約された)名前空間名 "http://www.w3.org/XML/1998/namespace"にある属性を追加したいとします。

幸い私が以前に書いたように、これらの属性は名前空間が暗黙的です。

$envelope->setAttribute('xmlns:a', 'http://www.w3.org/2005/08/addressing'); 

その後、XMLになり、あなたが探している:

<?xml version="1.0"?> 
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"/> 

これは前に回答されていますが、あなたが「通常」の属性のようにそれらを追加し、それがどの名前空間O/Wであります私は今、既存のQ &の資料を見つけることができません。

それは簡単です。おそらく属性を直接追加する方法がわからなかったため、間違った名前空間名で属性を追加するのは間違いでした。ここでは、 "xml"(大文字小文字を区別しないbtw。)で始まるすべての属性はと予約されており、暗黙の意味を持っていることに注意してください。その第二の名前空間名を指定して子要素を追加するたとえば

正しく文書に追加されます:

$test = $doc->createElementNS('http://www.w3.org/2005/08/addressing', 'a:test'); 
$doc->documentElement->appendChild($test); 

しかし、結果は冗長です:

<?xml version="1.0"?> 
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"> 
    <a:test xmlns:a="http://www.w3.org/2005/08/addressing"/> 
</s:Envelope> 

追加 "a:test"要素(xmlns:a="http://www.w3.org/2005/08/addressing")厳密に言えば、これは必ずしも必要ではありません(しかし、それは害ではありません。正しいです)。それは"Namespaces are not defined on or for a XML document, but on element nodes"です。あなたはすでにあなたが文書を再ロードすることができますし、同じコードは、余分な定義を追加しません文書要素のすべての名前空間接頭辞を指定している:

$doc = new DOMDocument(); 
$envelope = $doc->createElementNS('http://www.w3.org/2003/05/soap-envelope', 's:Envelope'); 
$doc->appendChild($envelope); 

$envelope->setAttribute('xmlns:a', 'http://www.w3.org/2005/08/addressing'); 

$doc->loadXML($doc->saveXML()); # reload the document 

$test = $doc->createElementNS('http://www.w3.org/2005/08/addressing', 'test'); 
$doc->documentElement->appendChild($test); 

を文書の出力はこれを示しています

<?xml version="1.0"?> 
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"> 
    <a:test/> 
</s:Envelope> 

これは、ドキュメントのリロード時に、DOMDocumentオブジェクトは、どの名前空間が既にプレフィックスされているかを知っており、その名前空間名のプレフィックスを再利用できるためです。技術的にはこれは必要ではありません(ドキュメントは同じです)。ドキュメントの同じテキストXMLシリアル化を作成することに関心がある場合は、面白いかもしれません。しかし、それは必要ではありません。接頭辞はまったく一致していてはなりません。

だから、あなたが単純だと思ったのは、実際にはかなり複雑です(その答えを読むためのテキストの長さを想像してください)。代わりに、必要な場所で名前空間の要素と属性を追加し、ネームスペースを適切に登録するために拡張機能が処理するようにします。これがAPIの目的です。テキスト表現にあまり集中しないでください(同じテキスト結果を作成する方法をここに示しました)。キーは、名前空間とAPIの使用方法を理解することです。同じテキスト表現を探しているだけでは、より多くの(多くの場合、あまりにも多くの)作業が可能ですが、可能ではありますが単純ではありません。

+0

まず、私は、あなたがどれほど多くの時間を費やしてくれているか、それほど詳細な答えにどれほど感謝していますか。おそらく私はあなたのより大きな "InvalidSecurity"問題を解決するためにあなたを雇うべきです;-)。とにかく、悲しいことに、setAttributeメソッドは私が試したものの1つで、無視するだけで、まったくやっていないかのように。私はこの質問に私のテストURLを入れても安全かどうかはわかりませんが、私はあなたに見て喜んでいます。記録のために、私はちょうど原因としてそれを排除する例を正確に複製しようとしています。 –

+0

@DaveSpencer:実際の例を掲載しました。こちらをご覧ください:: https://3v4l.org/TviiW - トラブルシューティングが容易になるように例を分けることができますか? – hakre

+0

あなたのワードプレスのブログにメッセージを残しました –