生成 PHP 代码,该代码将使用 XMLWriter 生成目标 XML
Generate PHP code that would generate target XML with XMLWriter
现在,使用 XMLWriter
从 PHP 创建 XML 文件并不难,如下所示:
$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();
但是,如果我已经有一个 "template" 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()
to cycle through the attributes, finally moving back to the element with 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))
);
}
(这里我稍微重构了你的代码,使测试更容易。)
现在,使用 XMLWriter
从 PHP 创建 XML 文件并不难,如下所示:
$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();
但是,如果我已经有一个 "template" 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()
to cycle through the attributes, finally moving back to the element with 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))
);
}
(这里我稍微重构了你的代码,使测试更容易。)