根据根标记转换xml文件

本文关键字:xml 文件 转换 | 更新日期: 2023-09-27 17:54:23

我有一个我想要读取的xml文件。根据根标签的不同,我在之前执行xsl-transform并读取修改后的文件:

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块中添加了这些行:
using (var stream = new FileStream(newFileName, FileMode.Create))
{
    reader.Close();
    reader = XmlReader.Create(myFile);
    transformer.Transform(reader, new XsltArgumentList(), stream);
}

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

根据根标记转换xml文件

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

我在这里找到了一个方法。实际上,我不需要阅读整个文档(如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声明或任何注释一样的"xml块"。