2016-08-03 73 views
0

,不难从PHP创建XML文件与XMLWriter这样的:生成PHP代码,将生成XMLWriter的目标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为abount半小时,我也可以:

1)autommaticly生成这样的代码,使用一些程序解析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" />,但仍比没有好。任何人都知道如何使属性起作用?

回答

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)) 
    ); 
} 

(这里我重构你的代码位,使测试更加简单。)