将一个XML DOM的一部分复制到另一个XML DOM以进行XSL转换(.NET)

时间:2009-07-21 21:50:09

标签: c# .net xml xslt

.NET 3.5中的XML和DOM的范围非常大,以至于我无法使用简单的解决方案来解决我的问题,而不会使用太多的乱码代码。由于这里的人总是提出一些优雅的解决方案,我认为这将是一个很好的问题。

如何接收在根“报告”节点下具有n个“单元”节点实例的XML文件(我在程序中先前创建并保存),以创建具有“报告”的XML DOM价值观和一个'单位'。

我需要为每个单元执行此操作,然后使用新XML DOM上的现有XSL转换样式表创建HTML文件。我已经可以让它适用于所有单元(现有的XML文件),但我需要为每个单元提供一份报告。

编辑(根据评论请求):

它看起来像什么:

<report>
  <report_name>Name</report_name>
  <report_date>yyyy/mm/dd</report_date>
  <unit>
    <ip>127.0.0.1</ip>
    <label>localhost</label>
    ..etc
  </unit>
  <unit>
    <ip>255.255.255.255</ip>
    <label>broadcast</label>
    ..etc
  </unit>
<report>

我想要每个人:

<report>
  <report_name>Name</report_name>
  <report_date>yyyy/mm/dd</report_date>
  <unit>
    <ip>127.0.0.1</ip>
    <label>localhost</label>
    ..etc
  </unit>
</report>

<report>
  <report_name>Name</report_name>
  <report_date>yyyy/mm/dd</report_date>
  <unit>
    <ip>255.255.255.255</ip>
    <label>broadcast</label>
    ..etc
  </unit>
<report>

2 个答案:

答案 0 :(得分:1)

foreach (XmlElement xmlUnit in xmlMain.SelectNodes("/report/unit"))
{
    var xmlDest = new XmlDocument();
    xmlDest.AppendChild(xmlDest.CreateElement("report"));

    // Add the report properties...
    foreach ( XmlElement xmlValue in xmlMain.SelectNodes( "/report/report_name | /report/report_date" ) )
        xmlDest.DocumentElement.AppendChild(xmlDest.ImportNode(xmlValue, true));

    // Add the "<unit>" element from the main document...
    xmlDest.DocumentElement.AppendChild(xmlDest.ImportNode(xmlUnit, true));

    // Now generate report using xmlDest
}

答案 1 :(得分:0)

如果您不需要访问unit元素之外的信息,则可以执行以下操作:

foreach (XmlNode n in d.SelectNodes("/report/unit"))
{
   using (StringReader sr = new StringReader(n.OuterXml))
   using (XmlReader xr = XmlReader.Create(sr))
   using (XmlWriter xw = XmlWriter.Create(Console.Out))
   {
       xslt.Transform(xr, xw);
   }
}

这种方法的缺点是XSLT只能访问所选节点中的XML。如果需要在文档的其他位置访问XML,则需要告知转换要处理的节点:

for (int i = 0; i < d.SelectNodes("/report/unit").Count; i++)
{
    XsltArgumentList args = new XsltArgumentList();
    args.AddParam("position", "", i + 1);
    using (StringReader sr = new StringReader(d.OuterXml))
    using (XmlReader xr = XmlReader.Create(sr))
    using (XmlWriter xw = XmlWriter.Create(Console.Out))
    {
        xslt.Transform(xr, args, xw);
    }
}

...让您的XSLT包括以下内容:

<xsl:param name="position"/>
<xsl:template match="/">
    <xsl:apply-templates select="/report/unit[$position=position()]"/>
</xsl:template>