Теперь нетрудно создать XML-файлы из PHP с 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
за полчаса, или я мог бы:
1) Создайте такой код автоматически, используйте программу, которая анализирует XML (Java, C #, PHP и т. Д.), Читает теги и атрибуты и генерирует соответствующий код PHP, который, в свою очередь, генерирует исходный XML. Это очень поможет.
2) Просто отмените <?php
пометить с ?>
и дамп XML напрямую, только добавляя <?php echo $value ?>
где необходимо, используйте хитрость, чтобы не записывать это в стандартный вывод, а вместо этого хранить в строке. Это было бы приемлемо, если бы эта хитрость не вызывала помещение этого внутри собственного скрипта и получение результата с помощью curl.
Так что, по вашему мнению, лучший вариант? Мне это нужно для экспорта диаграмм с помощью PHPExcel, многие вещи, которые мне нужны, просто не поддерживаются PHPExcel, особенно в области диаграмм, поэтому я просто смотрю на нужные файлы XML и генерирую их сам.
РЕДАКТИРОВАТЬ:
Это мой прогресс в создании кода на 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" />
, но все же лучше, чем ничего. Кто-нибудь знает, как заставить работать атрибуты?
В отличие от дочерних элементов, атрибуты загружаются одновременно с загрузкой самого узла элемента. Таким образом, когда 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))
);
}
(Здесь я немного переработал ваш код, чтобы облегчить тестирование.)
Других решений пока нет …