DOM: düğümleri ithalat ve onlara farklı ad öneki vermek nasıl

2 Cevap php

Ben diğer bazı belge elemanının düğümleri bir ağaç ithalatı için DOMDocument::importNode yöntemi ile aşina değilim.

Ben onları ithal otomatik olarak, düğümlerden oluşan bir ağaç üzerinde ad öneki değiştirmek yani, bu ad tüm düğümler için yeni bir öneki belirtebilirsiniz eğer Ancak, ne ben merak idi.

Düğümleri, mevcut belgede, tüm böylece "adı", "kimlik" ve benzeri isimler var söylüyorlar. Benim yeni belgeye bunları alırken onlar başka ad yanında olacak, bu yüzden onlara "nicnames: adı" olarak görünmesini istiyorum: böylece ve, "kimlik nicnames". : Başka bir bağlamda ben "isim myprefix", örneğin, bunları ithal etmek mümkün olabilir, böylece ben programlı bu öneki değiştirmek mümkün olmak istiyorum "myprefix: kimlik" onlar ithal konum belgeye bağlı.

Edit: as per the explanation in my answer, I figured out I don't actually need to do this. I was misunderstanding namespaces in XML.

2 Cevap

Ben yanlış XML ad olur keşfetti. Onlar aslında onlar sanıyordum çok daha iyidir.

Tek bir belgede kullanılan her XML ad farklı bir ad alanı öneki var olduğunu düşünmüştüm. Bu doğru değildir.

Nerede uygun nitelik sadece xmlns dahil ederek, önekleri olmadan bile belge boyunca farklı ad kullanmak, ve xmlns sadece kadar yüksek ayarlanmış olabilir bu önek için ad geçersiz kılma, bu eleman ve onun soyundan gelenler için etkisi yükledikleri olabilir ağaç.

Örneğin, içinde başka bir ad var, sen yapmak zorunda değilsiniz:

<record xmlns="namespace1">
  <person:surname xmlns:person="namespace2">Smith</person:surname>
</record>

Sadece yapabilirsiniz

<record xmlns="namespace1">
  <surname xmlns="namespace2">Smith</person>
</record>

Sadece farklı bir ad içerisinde başka bir belge de dahil olmak üzere zaman önek gerekli değildir bazı durumlarda iyi bir kısayol vardır, ama.

Muhtemelen sonra kendi ithalat kodu yazmak zorunda. Örneğin

function importNS(DOMNode $target, DOMNode $source, $fnImportElement, $fnImportAttribute) {
  switch($source->nodeType) {
    case XML_ELEMENT_NODE:
      // invoke the callback that creates the new DOMElement node
      $newNode = $fnImportElement($target->ownerDocument, $source);
      if ( !is_null($newNode) && !is_null($source->attributes) ) {
        foreach( $source->attributes as $attr) {
          importNS($newNode, $attr, $fnImportElement, $fnImportAttribute);
        }
      }
      break;
    case XML_ATTRIBUTE_NODE:
      // invoke the callback that creates the new DOMAttribute node
      $newNode = $fnImportAttribute($target->ownerDocument, $source);
      break;
    default:
      // flat copy
      $newNode = $target->ownerDocument->importNode($source);
  }

  if ( !is_null($newNode) ) {
    // import all child nodes
    if ( !is_null($source->childNodes) ) {
      foreach( $source->childNodes as $c) {
        importNS($newNode, $c, $fnImportElement, $fnImportAttribute);
      }
    }
    $target->appendChild($newNode);
  }
}

$target = new DOMDocument;
$target->loadxml('<foo xmlns:myprefix="myprefixUri"></foo>');

$source = new DOMDocument;
$source->loadxml('<a>
  <b x="123">...</b>
</a>');

$fnImportElement = function(DOMDocument $newOwnerDoc, DOMElement $e) {
  return $newOwnerDoc->createElement('myprefix:'.$e->localName);
};

$fnImportAttribute = function(DOMDocument $newOwnerDoc, DOMAttr $a) {
  // could use namespace here, too....
  return $newOwnerDoc->createAttribute($a->name);
};

importNS($target->documentElement, $source->documentElement, $fnImportElement, $fnImportAttribute);
echo $target->savexml();

baskılar

<?xml version="1.0"?>
<foo xmlns:myprefix="myprefixUri"><myprefix:a>
  <myprefix:b x="123">...</myprefix:b>
</myprefix:a></foo>