2012-03-12 8 views
2

こんにちは私はこれらの3つのトピックをまとめてXMLエントリを更新することに関して多くの質問があることを知っていますが、DOMXmlとXpathを使用してXMLエントリを更新する

私はXPathとその方法を理解しようとしばらく時間を費やしていましたが、私はまだやりたいことを得ることができません。

ここでは、私は私がやりたい何、このXMLファイル

<?xml version="1.0" encoding="UTF-8"?> 
<storagehouse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="schema.xsd"> 
    <item id="c7278e33ef0f4aff88da10dfeeaaae7a"> 
     <name>HDMI Cable 3m</name> 
     <weight>0.5</weight> 
     <category>Cables</category> 
     <location>B3</location> 
    </item> 
    <item id="df799fb47bc1e13f3e1c8b04ebd16a96"> 
     <name>Dell U2410</name> 
     <weight>2.5</weight> 
     <category>Monitors</category> 
     <location>C2</location> 
    </item> 
    </storagehouse> 

を持って

を行くが、私がする必要がある時には、上記/編集にいずれかのノードを更新することです。私はそれのためのHTMLフォームを行います。 しかし、私が一番大切なのは、目的のノードを見つけて更新する方法です。

ここで私はとても一人のユーザーが目的のノードを更新することを決定し、私はそれを見つけることができる、私は

<?php 

function fnDOMEditElementCond() 
    { 
     $dom = new DOMDocument(); 
     $dom->load('storage.xml'); 
     $library = $dom->documentElement; 
     $xpath = new DOMXPath($dom); 
     // I kind of understand this one here 
     $result = $xpath->query('/storagehouse/item[1]/name'); 
     //This one not so much 
     $result->item(0)->nodeValue .= ' Series'; 
     // This will remove the CDATA property of the element. 
     //To retain it, delete this element (see delete eg) & recreate it with CDATA (see create xml eg). 

     //2nd Way 
     //$result = $xpath->query('/library/book[author="J.R.R.Tolkein"]'); 
     // $result->item(0)->getElementsByTagName('title')->item(0)->nodeValue .= ' Series'; 
     header("Content-type: text/xml"); 
     echo $dom->saveXML(); 


    } 
?> 

を行うにしようとしています何のいくつかは、誰かが多分私のように属性としての例を与えることができる持っていますノードをXPathで更新してから更新しますか?

+1

*(ヒント)* http://schlitt.info/opensource/blog/0704_xpath.html – Gordon

+0

'storagehouse'はルート要素('/')ですので、'/storagehouse'を使用しないでください。 '/'だけです。 –

答えて

4

次の例では、DOMDocumentの親友であるsimplexmlを利用しています。表示されているxpathはどのメソッドを使用しているかに関係なく同じですが、ここではsimplexmlを使用してコードを低く抑えています。私は後でより高度なDOMDocumentの例を示します。

xpathについて:ノードを見つけて更新する方法まず、どのノードを見つけるために、すべての:

ノードは、要素/タグ名itemがあります。 XMLドキュメントのルート要素であるstoragehouse要素の中で探しています。

/storagehouse/item 

ルートから、最初storagehouse、その後、item:ドキュメント内のすべてのitem要素は、XPathでこのように表現されています。 /で区切られています。あなたはすでにそれを知っているので、面白いのは、特定のIDを持つ要素だけを取る方法です。述語が使用されていることについて、最後に追加しました:

/storagehouse/item[@id="id"] 
これは、再び、すべての itemの要素を返しますが、今回は唯一の値 id(文字列)を持つ属性 idを有するもの。

$xml = <<<XML 
<?xml version="1.0" encoding="UTF-8"?> 
<storagehouse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="schema.xsd"> 
    <item id="c7278e33ef0f4aff88da10dfeeaaae7a"> 
     <name>HDMI Cable 3m</name> 
     <weight>0.5</weight> 
     <category>Cables</category> 
     <location>B3</location> 
    </item> 
    <item id="df799fb47bc1e13f3e1c8b04ebd16a96"> 
     <name>Dell U2410</name> 
     <weight>2.5</weight> 
     <category>Monitors</category> 
     <location>C2</location> 
    </item> 
</storagehouse> 
XML; 

ことのxpath:以下XMLとあなたのケースでは例えば、(そのIDで、そのような項目が存在するため)

/storagehouse/item[@id="df799fb47bc1e13f3e1c8b04ebd16a96"] 

は、コンピュータのモニタを返します。同じid値を持つ複数のアイテムがある場合は、複数のアイテムが返されます。何もない場合、返されることはありません。それでは、コード例にそのラップをしてみましょう:

この例では
$simplexml = simplexml_load_string($xml); 
$result = $simplexml->xpath(sprintf('/storagehouse/item[@id="%s"]', $id)); 
if (!$result || count($result) !== 1) { 
    throw new Exception(sprintf('Item with id "%s" does not exists or is not unique.', $id)); 
} 
list($item) = $result; 

$titemは、そのコンピュータのモニターXML要素名項目のSimpleXMLElementオブジェクトです。

は、だから今、あなたの場合にはSimpleXMLと非常に簡単で、変更のために:

$item->category = 'LCD Monitor'; 

そして最後に結果を参照するには:

echo $simplexml->asXML(); 

はい、それはあなたのケースでSimpleXMLですべてです。

DOMDocumentでこれを実行したい場合は、非常によく似ています。ただし、要素の値を更新するには、その項目の子要素にもアクセスする必要があります。まず最初にアイテムをフェッチする次の例を見てみましょう。あなたは上記のSimpleXML例と比較した場合、あなたは物事が本当に異なっていないことがわかります。

$doc = new DOMDocument(); 
$doc->loadXML($xml); 
$xpath = new DOMXPath($doc); 
$result = $xpath->query(sprintf('/storagehouse/item[@id="%s"]', $id)); 
if (!$result || $result->length !== 1) { 
    throw new Exception(sprintf('Item with id "%s" does not exists or is not unique.', $id)); 
} 
$item = $result->item(0); 

ここでも、$itemは、コンピュータモニタの項目のXML要素が含まれています。しかし今度はDOMElementとなります。そこにあるcategory要素(またはもっと正確にはnodeValue)を変更するには、その子を最初に取得する必要があります。あなたは、XPathで再びこれを行うことができますが、$item要素に対する発現とこの時間:

./category 

は常にitem要素でcategory子要素があると仮定すると、これは、のように書くことができます

$category = $xpath->query('./category', $item)->item(0); 

$category$itemの最初のcategory子要素が含まれていません。どのような残っていることは、それの値を更新している:

$category->nodeValue = "LCD Monitor"; 

そして最後に結果を確認する:

echo $doc->saveXML(); 

をそして、それはこれだけです。 SimpleXMLまたはDOMDocumentのどちらを選択するかは、必要に応じて異なります。両方を切り替えることもできます。おそらく、マップや変更をチェックすることをお勧めします:

$repository = new Repository($xml); 
$item = $repository->getItemByID($id); 
$item->category = 'LCD Monitor'; 
$repository->saveChanges(); 
echo $repository->getXML(); 

当然のことながら、これはこの答えのためのあまりである、more codeが必要です。

+0

すごくありがとう、他の多くの人がこれを非常に便利に見つけられると確信しています!! –

関連する問題