【问题标题】:transform xml-file depending on root-tag根据根标签转换 xml 文件
【发布时间】:2016-07-04 09:47:15
【问题描述】:

我有一个想要阅读的 xml 文件。根据根标签,我之前正在执行 xsl 转换并读取修改后的文件:

XmlReader reader = XmlReader.Create(myFile);

var root = new XmlDocument();
root.Load(reader);
if (root.DocumentElement.Name == "FC_FeatureCatalogue")
{
    var xsltDoc = new XmlDocument();
    xsltDoc.Load("myXslt.xsl"));

    XsltSettings xsltSettings = new XsltSettings(false, true);
    var transformer = new XslCompiledTransform();
    transformer.Load(xsltDoc, xsltSettings, new XmlUrlResolver());

    using (var stream = new FileStream(newFileName, FileMode.Create))
    {
        transformer.Transform(reader, new XsltArgumentList(), stream);
    }
}

当条件通过时,由newFileName 确定的文件被创建。但是,它确实只包含一个空条目。所以我调试了一下,注意到在调用root.Load(reader) 时,文件被读取到EOF。这就是为什么我假设当使用相同的文件进行转换时,转换器根本不做任何事情,因为读者没有更多的内容。

那么有没有办法重新设置阅读器(我知道,XmlReader 是“仅转发”)或者在不读取 EOF 的情况下获取原始 xml 文件的根标记并对其进行转换?

编辑:为了验证我的假设,我还在using-block 中添加了这些行:

using (var stream = new FileStream(newFileName, FileMode.Create))
{
    reader.Close();
    reader = XmlReader.Create(myFile);
    transformer.Transform(reader, new XsltArgumentList(), stream);
}

现在创建的文件包含所有预期的数据。不过,我希望有一种方法可以读取根标签并转换文件,而无需重新编辑整个文件。

【问题讨论】:

  • 试试这个:XmlReader reader = XmlReader.Create(myFile); reader.MoveToContent(); if (reader.Name == "FC_FeatureCatalogue") { }
  • @jdweng Yeap,成功了。

标签: c# xslt xmlreader


【解决方案1】:

我看不到在 XmlReader 中重置流的方法。

一种方法是更直接地使用流,如下所示。

  using (FileStream fs = File.Create(myFile))
  {
    var root = new XmlDocument();

    root.Load(fs);

    if (root.DocumentElement.Name == "FC_FeatureCatalogue")
    {
      var xsltDoc = new XmlDocument();
      xsltDoc.Load("myXslt.xsl"));

      XsltSettings xsltSettings = new XsltSettings(false, true);
      var transformer = new XslCompiledTransform();
      transformer.Load(xsltDoc, xsltSettings, new XmlUrlResolver());

      fs.Seek(0, SeekOrigin.Begin);

      using (StreamReader sr = new StreamReader(fs))
      {
        XmlReader reader = XmlReader.Create(sr);
        using (var stream = new FileStream(newFileName, FileMode.Create))
        {
          transformer.Transform(reader, new XsltArgumentList(), stream);
        }            
      }
    }
  }

【讨论】:

    【解决方案2】:

    我发现了一种受到here 启发的方法。实际上,我不需要阅读整个文档(就像XmlDocument.Load 所做的那样),只需要获取根元素。所以我只是简单地阅读了读者的第一行:

    while (reader.Read()) 
    {
        if (reader.NodeType == XmlNodeType.Element) break;
    }
    if (reader.Name == "FC_FeatureCatalogue")
    {
        // ...
    }
    

    或者,您也可以按照 jdweng 的建议使用它,它有点短:

    reader.MoveToContent();
    if (reader.NodeType == XmlNodeType.Element) { ... }
    

    令我惊讶的是,尽管读者的内部位置现在位于文档中的某个位置,但我们可以适当地转换 xml。我猜这是因为之前读取的元素只是“xml-chunk”,如 xml-declaration 或任何 cmets。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-26
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 2022-01-20
      • 2020-05-31
      • 2013-08-31
      • 2017-11-01
      相关资源
      最近更新 更多