2014-11-12 2 views
0

Я хотел бы создать XML-документ с очень конкретным форматом. Это должно выглядеть примерно так:Задайте пространство имен для XML-тега с помощью PHP

<?xml version="1.0" encoding="UTF-8"?> 
<ram:FLOW xmlns:ram=\"http://MY_LIBRARY\" xmlns:mar=\"http://ANOTHER_LIBRARY\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> 
<Header> 
<Source>Application1</Source> 
<Time>2014-11-12T12:46:39</Time> 
<Environment>TEST</Environment> 
<Sequence>537</Sequence> 
</Header> 
<Data> 
<mar:OC_DC> 
<DC_elements> 
<Unit> 
<Unit_ID>089789</Unit_ID> 
<State>active</State> 
</Unit> 
<Unit> 
<Unit_ID>459008</Unit_ID> 
<State>inactive</State> 
</Unit> 
</DC_elements> 
</mar:OC_DC> 
</Data> 
</ram:FLOW> 

Я написал PHP/скрипт MySQL для создания этого документа:

<?php 
$xml = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"UTF-8\"?><ram:FLOW xmlns:ram=\"http://MY_LIBRARY\" xmlns:mar=\"http://ANOTHER_LIBRARY\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"></ram:FLOW>"); 

$header = $xml->addChild('Header'); 
$header->addChild('Source', $source); 
$header->addChild('Time', $time); 
$header->addChild('Environment', $env); 
$header->addChild('Sequence', $sequence); 

$data=$xml->addChild('Data'); 
$mar_oc_dc=$data->addChild('mar:OC_DC'); 
$dc_elements=$mar_oc_dc->addChild('DC_elements'); 

while($condition) 
{ 
    // some MySQL code here to extract unit_id and state 
    $unit=$dc_elements->addChild('Unit'); 
    $unit_id=$unit->addChild('Unit_ID', $unit_id); 
    $state=$unit->addChild('State', $state); 
} 

$dom = new DOMDocument(); 
$dom->preserveWhiteSpace = FALSE; 
$dom->formatOutput = TRUE; 
$dom->loadXML($xml->asXML()); 
$handle = fopen("backup/" . $file_name . ".xml", "w"); 
fwrite($handle, $dom->saveXML()); 
fclose($handle);    
?> 

Но результат был немного отличается от того, что я ожидал:

<?xml version="1.0" encoding="UTF-8"?> 
<FLOW xmlns:ram=\"http://MY_LIBRARY\" xmlns:mar=\"http://ANOTHER_LIBRARY\"  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> 
<Header> 
<Source>Application1</Source> 
<Time>2014-11-12T12:46:39</Time> 
<Environment>TEST</Environment> 
<Sequence>537</Sequence> 
</Header> 
<Data> 
<OC_DC> 
<DC_elements> 
<Unit> 
<Unit_ID>089789</Unit_ID> 
<State>active</State> 
</Unit> 
<Unit> 
<Unit_ID>459008</Unit_ID> 
<State>inactive</State> 
</Unit> 
</DC_elements> 
</OC_DC> 
</Data> 
</FLOW> 

Как вы можете видеть, баран: FLOW тег стал FLOW и mar: OC_DC бирка стал OC_DC. Я смотрел Stack Overflow и другие веб-сайты для решения и не смог его найти. Не могли бы вы дать мне руку с этим?

Заранее спасибо.

ответ

1

Атрибуты xmlns: * - это определения пространства имен (а не библиотеки). Значение этих атрибутов - это уникальная строка, которая идентифицирует формат/стандарт, к которым принадлежат элементы.

Атрибуты определяют префикс для уникальной строки, так что документ XML меньше и читабельнее.

Если вы хотите создать элемент (или атрибут) внутри пространства имен, вам необходимо предоставить пространство имен. В SimpleXMlElement третьим аргументом является пространство имен.

Кажется, что элементы добавляются в пространство имен родительского узла, если не указано пространство имен. Это означает, что вы должны предоставить пустую строку для любого элемента без пространства имен.

$root = new SimpleXMlElement('<ram:FLOW xmlns:ram="http://MY_LIBRARY" xmlns:mar="http://ANOTHER_LIBRARY"/>'); 
$root->addChild('header', null, ''); 
$data = $root->addChild('data', null, ''); 
$data->addChild('mar:OC_DC', null, 'http://ANOTHER_LIBRARY'); 

echo $root->asXml(); 

Выход:

<?xml version="1.0"?> 
<ram:FLOW xmlns:ram="http://MY_LIBRARY" xmlns:mar="http://ANOTHER_LIBRARY"> 
    <header xmlns=""/> 
    <data xmlns=""> 
     <mar:OC_DC/> 
    </data> 
</ram:FLOW> 

Я не нашел способ избежать пустых Xmlns атрибутов.

DOM более подробно. Логика create и append является отдельной.

const XMLNS_RAM = 'http://MY_LIBRARY'; 
const XMLNS_MAR = 'http://ANOTHER_LIBRARY'; 

$dom = new DOMDocument(); 
// appending an element with a namespace with define it if needed 
$root = $dom->appendChild($dom->createElementNS(XMLNS_RAM, 'ram:FLOW')); 
// setting the xmlns attribute explicit avoids the definition in descendant nodes 
$root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:mar', XMLNS_MAR); 
$root->appendChild($dom->createElement('header')); 
$data = $root->appendChild($dom->createElement('data')); 
$data->appendChild($dom->createElementNS(XMLNS_MAR, 'mar:OC_DC')); 

$dom->formatOutput = true; 
echo $dom->saveXml(); 

Выход:

<?xml version="1.0"?> 
<ram:FLOW xmlns:ram="http://MY_LIBRARY" xmlns:mar="http://ANOTHER_LIBRARY"> 
    <header/> 
    <data> 
    <mar:OC_DC/> 
    </data> 
</ram:FLOW> 
+0

Используя свое первое предложение дали различные результаты, чем ожидалось. Все узлы в ** mar: OC_DC ** имели префикс ** mar: ** в результате. Но ваше второе предложение, используя DOM, дало точный результат, который я искал. Огромное спасибо. – Sevigne

+0

Как я уже писал, SimpleXMLElement по умолчанию использует пространство имен родительского элемента. Поэтому вам всегда нужно предоставить пространство имен (как пустую строку). Даже для элементов, которые не имеют пространства имен. – ThW

Смежные вопросы