生成将使用 XMLWriter 生成目标 XML 的 PHP 代码

Posted

技术标签:

【中文标题】生成将使用 XMLWriter 生成目标 XML 的 PHP 代码【英文标题】:Generate PHP code that would generate target XML with XMLWriter 【发布时间】:2016-12-09 17:44:38 【问题描述】:

现在,使用XMLWriterphp 创建 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();

但是,如果我已经有一个“模板”XML 文件(比如说大约 30 多行),我想通过这样的 PHP 生成该文件,其中很少有由 PHP 脚本计算的属性。

现在我可以去写startElementwriteAttributeendElement 大约半小时,或者我可以:

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;
                
            
        
    

效果很好,只是它不解析属性(就像在&lt;tag attrName="attValue" /&gt; 中一样,但总比没有好。有人知道如何使属性起作用吗?

【问题讨论】:

【参考方案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))
    );

(这里我对您的代码进行了一些重构,以使测试更容易。)

【讨论】:

以上是关于生成将使用 XMLWriter 生成目标 XML 的 PHP 代码的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NET 中使用 XmlWriter 创建 XmlDocument?

可以使用 XmlWriter 将 XML 写入内存吗?

XmlWriter 写入字符串而不是文件

PHP读取及生成xml文件实测

使用XmlWriter写Xml

PHP和XmlWriter更改缩进字符串