2016-08-03 2 views
0

Теперь, это не трудно создать XML-файлы из PHP с XMLWriter, как это:Генерация PHP кода, который будет генерировать целевой XML с XMLWriter

$objWriter->startDocument('1.0', 'UTF-8', 'yes'); 

// Data 
$objWriter->startElement("Relationships"); 
$objWriter->writeAttribute("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships"); 

$objWriter->startElement("Relationship"); 
$objWriter->writeAttribute("Id", "rId1"); 
$objWriter->writeAttribute("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartUserShapes"); 
$objWriter->writeAttribute("Target", "../drawings/drawing" . $drawingNum . ".xml"); 
$objWriter->endElement(); // Relationship 

$objWriter->endElement(); // Relationships 

$result = $objWriter->getData(); 

Однако, что если у меня уже есть «шаблон» XML-файл (скажем, более 30 строк), которые я хочу генерировать с помощью PHP, например, с несколькими атрибутами, которые здесь и там вычисляются с помощью PHP-скрипта.

Теперь я мог бы пойти и написать startElement, writeAttribute и endElement за abount полчаса, или я мог бы:

1) Создание такого кода autommaticly, использовать какую-то программу, анализирующую XML (Java, C#, PHP, независимо от), читать теги и атрибуты и генерировать соответствующий PHP-код, который, в свою очередь, генерирует исходный XML. Это очень помогло бы.

2) Просто отменить <?php тег с ?> и свалка XML напрямую, только добавляя <?php echo $value ?>, где это необходимо, а затем использовать некоторые хитрости, чтобы не написать это на стандартный вывод, но сохранить его в виде строки. Это было бы приемлемо, если бы эта обманка не вызывала его внутри этого собственного скрипта и получала результат через завиток.

Итак, как вы думаете, это лучший вариант? Мне нужно это для экспорта диаграмм с PHPExcel, многое из того, что мне нужно, просто не поддерживается PHPExcel, особенно в области диаграммы, поэтому я просто смотрю на нужные XML-файлы и сам их создаю.

EDIT:

Это мой прогресс до сих пор с генерации кода в C#:

private static void doWork(string filename, Func<string, string> onElementStart, Func<string, string> onElementEnd, Func<string, string, string> onAttribute) 
{ 
    using (XmlReader reader = XmlReader.Create("file:///" + filename)) 
    { 
     using (StreamWriter file = new StreamWriter(@"c:\kajacx\other\troll_excel5\output.php")) 
     { 
      // Parse the file and display each of the nodes. 
      while (reader.Read()) 
      { 
       switch (reader.NodeType) 
       { 
        case XmlNodeType.Element: 
         file.WriteLine(onElementStart(reader.Name)); 
         break; 
        case XmlNodeType.Attribute: 
         file.WriteLine(onAttribute(reader.Name, reader.Value)); 
         break; 
        case XmlNodeType.EndElement: 
         file.WriteLine(onElementEnd(reader.Name)); 
         break; 
       } 
      } 
     } 
    } 
} 

работает довольно хорошо, за исключением того, оно не разобрать атрибуты (например, в <tag attrName="attValue" />, но все же лучше, чем ничего Кто-нибудь знает, как заставить атрибуты работать?

ответ

1

В отличие от дочерних элементов, атрибуты загружаются одновременно с загрузкой самого элемента элемента. Таким образом, когда reader.NodeType == XmlNodeType.Element, вы можете использовать XmlReader.MoveToNextAttribute() для цикла через атрибуты, наконец, движется обратно к элементу с XmlReader.MoveToElement():

private static void DoWork(XmlReader reader, Action<string> onElementStart, Action<string> onElementEnd, Action<string, string> onAttribute) 
{ 
    while (reader.Read()) 
    { 
     switch (reader.NodeType) 
     { 
      case XmlNodeType.Element: 
       onElementStart(reader.Name); 
       if (reader.HasAttributes) 
       { 
        while (reader.MoveToNextAttribute()) 
        { 
         onAttribute(reader.Name, reader.Value); 
        } 
        // Move the reader back to the element node. 
        reader.MoveToElement(); 
       } 
       if (reader.IsEmptyElement) 
       { 
        // Do something special for empty elements? 
       } 
       break; 
      case XmlNodeType.Attribute: 
       onAttribute(reader.Name, reader.Value); 
       break; 
      case XmlNodeType.EndElement: 
       onElementEnd(reader.Name); 
       break; 
     } 
    } 
} 

private static void doWork(string filename, Func<string, string> onElementStart, Func<string, string> onElementEnd, Func<string, string, string> onAttribute) 
{ 
    using (XmlReader reader = XmlReader.Create("file:///" + filename)) 
    { 
     using (StreamWriter writer = new StreamWriter(@"c:\kajacx\other\troll_excel5\output.php")) 
     { 
      DoWork(reader, writer, onElementEnd, onElementEnd, onAttribute); 
     } 
    } 
} 

private static void DoWork(XmlReader reader, TextWriter writer, Func<string, string> onElementStart, Func<string, string> onElementEnd, Func<string, string, string> onAttribute) 
{ 
    DoWork(reader, 
     (s) => writer.WriteLine(onElementStart(s)), 
     (s) => writer.WriteLine(onElementEnd(s)), 
     (s1, s2) => writer.WriteLine(onAttribute(s1, s2)) 
    ); 
} 

(Здесь я переработан ваш код немного, чтобы облегчить тестирование.)

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