重写大型XML文件 - 排除某些节点

时间:2016-09-11 13:35:51

标签: c# .net xml linq-to-xml

我想在没有一些节点的情况下重新编写一个大的xml。 我正在尝试使用system.xml.xmlreader逐行读取一个XML文件(100个MB,无法将其全部读取到内存中) - 努力寻找一种方法来读取它的一部分,将它们写成一个单独的xDocument然后将该xDocument保存到磁盘。

我一直在想的是:

      using (XmlReader reader = XmlReader.Create(_xml_path))
        {
            using (XmlWriter writer = XmlWriter.Create(@"filteredxml.xml"))
            {
                reader.MoveToContent();

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name != "EL_TO_BE_REMOVED")
                        {
                           //writer.WriteNode(reader.ReadOuterXml());

                        }
                    }
                }
            }
        }

但是reader.ReadOuterXml()只是转到第一个元素并将其所有后代写入文件,而不让我过滤掉我想忽略的元素。

2 个答案:

答案 0 :(得分:1)

这听起来像是XSLT的工作。

XSL Transform(RemoveElement.xslt):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="EL_TO_BE_REMOVED" />

</xsl:stylesheet>

执行转换的C#代码:

var transform = new XslCompiledTransform();
transform.Load("xslt/path/RemoveElement.xslt");

transform.Transform("input/xml/path/inputFile.xml", "output/xml/path/outputFile.xml");

答案 1 :(得分:0)

如果存在大文件和内存限制,则应使用SAX而不是DOM进行解析:XMLReader确实是C#等效。

这可能是一个基本方法,其中包含用于输入的XMLReader,用于输出的XMLWriter以及用于删除名为RemoveMe的节点(包含其所有内容)的计数器。

注意内部循环以克隆每个相关元素的属性。

 import UIKit
import Firebase

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

var dataFeed = [dataS]()
let pagingSpinner = UIActivityIndicatorView(activityIndicatorStyle: .Gray)
var totalNoOfPost : Int!



@IBOutlet weak var customTableView: UITableView!




override func viewDidLoad() {
    super.viewDidLoad()

    customTableView.delegate = self
    customTableView.dataSource = self
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    FIRDatabase.database().reference().child("Posts").observeSingleEventOfType(.Value, withBlock: {(snap) in

        if let postDict = snap.value as? [String:AnyObject]{

             self.totalNoOfPost = postDict.count

                self.loadMore()
        }
    })

}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return dataFeed.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = customTableView.dequeueReusableCellWithIdentifier("customCell") as! customTableViewCell
    if dataFeed.count > 0{
    cell.poatLabel.text = dataFeed[indexPath.row].postData
    }
    return cell
}

func loadMore(){

    let initialFeedCount : Int = dataFeed.count

    if totalNoOfPost - initialFeedCount - 4 > 0{

    FIRDatabase.database().reference().child("Posts").queryOrderedByChild("index").queryStartingAtValue(totalNoOfPost - initialFeedCount - 4).queryEndingAtValue(totalNoOfPost - initialFeedCount).observeEventType(.Value, withBlock: {(recievedSnap) in

        if recievedSnap.exists(){

        for each in recievedSnap.value as! [String:AnyObject]{
            let temp = dataS.init(post: each.1["text"] as! String, ind : each.1["index"] as! Int)
            self.dataFeed.insert(temp, atIndex: 5 * Int(self.dataFeed.count/5))
            self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
               if self.dataFeed.count == initialFeedCount+5{
                self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
                self.customTableView.reloadData()

            }
          }

         }
        }, withCancelBlock: {(err) in

            print(err.localizedDescription)


      })

    }else if totalNoOfPost - initialFeedCount - 4 <= 0{


        FIRDatabase.database().reference().child("Posts").queryOrderedByChild("index").queryStartingAtValue(0).queryEndingAtValue(totalNoOfPost - initialFeedCount).observeEventType(.Value, withBlock: {(recievedSnap) in

            if recievedSnap.exists(){

            for each in recievedSnap.value as! [String:AnyObject]{

                let temp = dataS.init(post: each.1["text"] as! String, ind : each.1["index"] as! Int)

                self.dataFeed.insert(temp, atIndex: 5 * Int(self.dataFeed.count/5))
                self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
                if self.dataFeed.count == initialFeedCount+4{
                   self.dataFeed.sortInPlace({$0.index_Initial > $1.index_Initial})
                    self.customTableView.reloadData()
                        self.pagingSpinner.stopAnimating()
                }
              }
            }else{

            self.pagingSpinner.stopAnimating()
            }

            }, withCancelBlock: {(err) in

                print(err.localizedDescription)


        })
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row + 1) == dataFeed.count {
        print("Displayed the last row!")


                    pagingSpinner.startAnimating()
                    pagingSpinner.hidesWhenStopped = true
                    pagingSpinner.sizeToFit()
                    customTableView.tableFooterView = pagingSpinner
                    loadMore()
    }
}


}


struct dataS {

var postData : String!
var index_Initial : Int!

init(post : String!, ind : Int!)
{
 self.postData = post
 self.index_Initial = ind
  }

}