从Xml文档中删除无关紧要的空格

时间:2014-05-30 20:23:08

标签: c# xml

我有一个包含重要和无意义空白的xml文件。我想读取这个文件并将文件写回磁盘,删除无关紧要的空格。在考虑重要的与无意义的空白时,我想确保混合内容元素(由我的模式定义)中的空间得到维护。我怎么能用C#做到这一点?

基于我读过的this article,听起来我可能需要使用验证的xml阅读器,以便读者知道哪些元素包含每个模式的混合内容。下面是我尝试过的一些代码的例子,这些代码在包含混合内容的父元素中的元素之间没有保留显着的空白。

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
using (XmlTextReader rdr = new XmlTextReader(xmlFilePath1))
{
    rdr.WhitespaceHandling = WhitespaceHandling.Significant;
    XmlSchemaSet sc = new XmlSchemaSet();
    sc.Add(null, @"C:\my-schema.xsd");
    doc.Load(XmlReader.Create(rdr, new XmlReaderSettings() { ValidationType = System.Xml.ValidationType.Schema, Schemas = sc }));
    using (XmlTextWriter writer = new XmlTextWriter(xmlFilePath2, Encoding.UTF8))
    {
        writer.Formatting = Formatting.None;
        doc.Save(writer);
    }
}

下面是我想要维护空格的xml示例。我期待维护两个内联标记元素之间的空白。 Para在模式中定义为具有混合内容。

<para>i have a bunch of text here with some <inlinetag attrib="a"/> <inlinetag attrib="b"/></para>

这是一个我想删除的空白的简单示例。在此示例中,标记来自一个打印的xml文档,其中元素前面有制表符或空格,后面有换行符。我希望将空格保留在para中,但不要在它之外。

  <entry colname="col2">
    <para>Lorem ipsum dolor sit amet, et nulla diam.<inlineTag value="a"/> <inlineTag value="b"/></para>
  </entry>

1 个答案:

答案 0 :(得分:1)

我确实找到了只编写重要空白的解决方案,尽管它必然像我希望的那样直截了当。下面是一些从Mark Fussell's blog大量借用的示例代码。我对他的WriteShallowNode方法进行的唯一修改是删除XmlNodeType.Whitespace的case语句。这会导致从输出中删除无关紧要的空格。

using (var xwModifiedXml = XmlWriter.Create(xmlFilePath1))
{
    using (var sr = new StringReader(File.ReadAllText(xmlFilePath2)))
    {
        XmlSchemaSet sc = new XmlSchemaSet();
        sc.Add(null, @"C:\my-schema.xsd");
        using (var xrModifiedXml = XmlReader.Create(sr, new XmlReaderSettings() { ValidationType = System.Xml.ValidationType.Schema, Schemas = sc }))
        {
            bool readResult = xrModifiedXml.Read();
            while (readResult)
            {
                WriteShallowNode(xrModifiedXml, xwModifiedXml);
                readResult = xrModifiedXml.Read();
            }
        }
    }
}

static void WriteShallowNode( XmlReader reader, XmlWriter writer )
{
      if ( reader == null )
      {
            throw new ArgumentNullException("reader");
      }
      if ( writer == null )
      {
            throw new ArgumentNullException("writer");
      }

      switch ( reader.NodeType )
      {
            case XmlNodeType.Element:
                  writer.WriteStartElement( reader.Prefix, reader.LocalName, reader.NamespaceURI );
                  writer.WriteAttributes( reader, true );
                  if ( reader.IsEmptyElement )
                  {
                        writer.WriteEndElement();
                  }
                  break;
            case XmlNodeType.Text:
                  writer.WriteString( reader.Value );
                  break;
            case XmlNodeType.SignificantWhitespace:
                  // only write significant whitespace
                  writer.WriteWhitespace(reader.Value);
                  break;
            case XmlNodeType.CDATA:
                  writer.WriteCData( reader.Value );
                  break;
            case XmlNodeType.EntityReference:
                  writer.WriteEntityRef(reader.Name);
                  break;
            case XmlNodeType.XmlDeclaration:
            case XmlNodeType.ProcessingInstruction:
                  writer.WriteProcessingInstruction( reader.Name, reader.Value );
                  break;
            case XmlNodeType.DocumentType:
                  writer.WriteDocType( reader.Name, reader.GetAttribute( "PUBLIC" ), reader.GetAttribute( "SYSTEM" ), reader.Value );
                  break;
            case XmlNodeType.Comment:
                  writer.WriteComment( reader.Value );
                  break;
            case XmlNodeType.EndElement:
                  writer.WriteFullEndElement();
                  break;
      }
}