根据根标签转换 xml-文件

transform xml-file depending on root-tag

我有一个 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。这就是为什么我假设当使用相同的文件进行转换时,转换器什么都不做,因为 reader 没有更多内容。

那么有没有办法重新设置 reader(我知道,XmlReader 应该是 "forward only")或者获取原始 "forward only" 的根标签=30=]-文件没有读取到 EOF 并转换它?

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

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

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

我看不到在 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);
        }            
      }
    }
  }

我发现了一种受到启发的方法 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-声明或任何注释。