فهرست منبع

xml录音分析程序

jiayi 1 سال پیش
والد
کامیت
64c3fad198

+ 63 - 0
.gitattributes

@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs     diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following 
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln       merge=binary
+#*.csproj    merge=binary
+#*.vbproj    merge=binary
+#*.vcxproj   merge=binary
+#*.vcproj    merge=binary
+#*.dbproj    merge=binary
+#*.fsproj    merge=binary
+#*.lsproj    merge=binary
+#*.wixproj   merge=binary
+#*.modelproj merge=binary
+#*.sqlproj   merge=binary
+#*.wwaproj   merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg   binary
+#*.png   binary
+#*.gif   binary
+
+###############################################################################
+# diff behavior for common document formats
+# 
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the 
+# entries below.
+###############################################################################
+#*.doc   diff=astextplain
+#*.DOC   diff=astextplain
+#*.docx  diff=astextplain
+#*.DOCX  diff=astextplain
+#*.dot   diff=astextplain
+#*.DOT   diff=astextplain
+#*.pdf   diff=astextplain
+#*.PDF   diff=astextplain
+#*.rtf   diff=astextplain
+#*.RTF   diff=astextplain

+ 261 - 0
.gitignore

@@ -0,0 +1,261 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+#*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc

+ 28 - 0
XmlDocumentAnalysis.sln

@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26228.4
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlDocumentAnalysis", "XmlDocumentAnalysis\XmlDocumentAnalysis.csproj", "{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|x64 = Debug|x64
+		Release|Any CPU = Release|Any CPU
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Debug|x64.ActiveCfg = Debug|x64
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Debug|x64.Build.0 = Debug|x64
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Release|x64.ActiveCfg = Release|x64
+		{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 40 - 0
XmlDocumentAnalysis/App.config

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <startup>
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+  </startup>
+  <appSettings>
+    <!--定时间隔时间-->
+    <add key="interval" value="60000" />
+    <!--最后一次拷贝记录目录-->
+    <add key="baseFilePath" value="C:\Users\13491\Desktop\鼎和" />
+    <!--拷贝分析起始时间(例子:)-->
+    <add key="copyStartTime" value="2023-02-13 00:00:00" />
+    <!--拷贝分析结束时间(例子:)-->
+    <add key="copyEndTime" value="2023-02-14 00:00:00" />
+    <!--xml底层目录400001的ftp地址-->
+    <add key="xmlBasePath" value="ftp://192.168.11.22/calls/400001/" />
+    <!--拷贝的xml底层目录-->
+    <add key="copyXmlFilePath" value="E:\Recording\400001" />
+    <!--csv路劲-->
+    <add key="csvBaseFilePath" value="C:\Users\13491\Desktop\鼎和\csv" />
+    <!--数据库连接-->
+    <!--<add key="default" value="User ID=SYSTEM;Password=123456;Data Source=(DESCRIPTION = (ADDRESS_LIST= (ADDRESS = (PROTOCOL = TCP)(HOST =127.0.0.1)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = ORCL)))"/>-->
+    <add key="default" value="User ID=SYSTEM;Password=Aa853276300;Data Source=(DESCRIPTION = (ADDRESS_LIST= (ADDRESS = (PROTOCOL = TCP)(HOST =192.168.11.22)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = SA)))" />
+    <!--数据库类型:oracle,sqlserver-->
+    <add key="defaultDBType" value="oracle" />
+    <add key="ClientSettingsProvider.ServiceUri" value="" />
+  </appSettings>
+  <system.web>
+    <membership defaultProvider="ClientAuthenticationMembershipProvider">
+      <providers>
+        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
+      </providers>
+    </membership>
+    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
+      <providers>
+        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
+      </providers>
+    </roleManager>
+  </system.web>
+</configuration>

+ 18 - 0
XmlDocumentAnalysis/FileLastTimeComparer.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XmlDucumentAnalysis
+{
+    public class FIleLastTimeComparer : IComparer<FileInfo>
+    {
+        public int Compare(FileInfo x, FileInfo y)
+        {
+            return y.LastWriteTime.CompareTo(x.LastWriteTime);//递减
+                                                              //return x.LastWriteTime.CompareTo(y.LastWriteTime);//递增
+        }
+    }
+}

+ 113 - 0
XmlDocumentAnalysis/Form1.Designer.cs

@@ -0,0 +1,113 @@
+namespace XmlDucumentAnalysis
+{
+    partial class Form1
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.button1 = new System.Windows.Forms.Button();
+            this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker();
+            this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker();
+            this.button2 = new System.Windows.Forms.Button();
+            this.删除录音文件 = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(415, 23);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(123, 23);
+            this.button1.TabIndex = 0;
+            this.button1.Text = "从ftp复制录音文件";
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // dateTimePicker1
+            // 
+            this.dateTimePicker1.CustomFormat = "yyyy-MM-dd HH:mm:ss";
+            this.dateTimePicker1.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+            this.dateTimePicker1.Location = new System.Drawing.Point(12, 21);
+            this.dateTimePicker1.Name = "dateTimePicker1";
+            this.dateTimePicker1.Size = new System.Drawing.Size(200, 25);
+            this.dateTimePicker1.TabIndex = 1;
+            this.dateTimePicker1.ValueChanged += new System.EventHandler(this.dateTimePicker1_ValueChanged);
+            // 
+            // dateTimePicker2
+            // 
+            this.dateTimePicker2.CustomFormat = "yyyy-MM-dd HH:mm:ss";
+            this.dateTimePicker2.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+            this.dateTimePicker2.Location = new System.Drawing.Point(12, 144);
+            this.dateTimePicker2.Name = "dateTimePicker2";
+            this.dateTimePicker2.Size = new System.Drawing.Size(200, 25);
+            this.dateTimePicker2.TabIndex = 2;
+            this.dateTimePicker2.ValueChanged += new System.EventHandler(this.dateTimePicker2_ValueChanged);
+            // 
+            // button2
+            // 
+            this.button2.Location = new System.Drawing.Point(415, 144);
+            this.button2.Name = "button2";
+            this.button2.Size = new System.Drawing.Size(123, 23);
+            this.button2.TabIndex = 3;
+            this.button2.Text = "生成csv文件";
+            this.button2.UseVisualStyleBackColor = true;
+            this.button2.Click += new System.EventHandler(this.button2_Click);
+            // 
+            // 删除录音文件
+            // 
+            this.删除录音文件.Location = new System.Drawing.Point(225, 219);
+            this.删除录音文件.Name = "删除录音文件";
+            this.删除录音文件.Size = new System.Drawing.Size(157, 23);
+            this.删除录音文件.TabIndex = 4;
+            this.删除录音文件.Text = "删除过期的录音文件";
+            this.删除录音文件.UseVisualStyleBackColor = true;
+            this.删除录音文件.Click += new System.EventHandler(this.button3_Click);
+            // 
+            // Form1
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(619, 287);
+            this.Controls.Add(this.删除录音文件);
+            this.Controls.Add(this.button2);
+            this.Controls.Add(this.dateTimePicker2);
+            this.Controls.Add(this.dateTimePicker1);
+            this.Controls.Add(this.button1);
+            this.Name = "Form1";
+            this.Text = "Form1";
+            this.Load += new System.EventHandler(this.Form1_Load);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.DateTimePicker dateTimePicker1;
+        private System.Windows.Forms.DateTimePicker dateTimePicker2;
+        private System.Windows.Forms.Button button2;
+        private System.Windows.Forms.Button 删除录音文件;
+    }
+}

+ 780 - 0
XmlDocumentAnalysis/Form1.cs

@@ -0,0 +1,780 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Configuration;
+using System.IO;
+using System.Security.Cryptography;
+using System.Timers;
+using System.Xml;
+using DataPumpWindowsService;
+using XmlDucumentAnalysis.model;
+using System.Net;
+using ICSharpCode.SharpZipLib.Tar;
+
+namespace XmlDucumentAnalysis
+{
+    public partial class Form1 : Form
+    {
+        public Form1()
+        {
+            InitializeComponent();
+        }
+
+        private System.Timers.Timer timer = new System.Timers.Timer();
+        private string baseFilePath
+        {
+            get;
+            set;
+        }
+        private string csvBaseFilePath
+        {
+            get;
+            set;
+        }
+        private string xmlBasePath
+        {
+            get;
+            set;
+        }
+        private string copyXmlFilePath
+        {
+            get;
+            set;
+        }
+        private string ConnectString
+        {
+            get;
+            set;
+        }
+        private DateTime minDateTime
+        {
+            get;
+            set;
+        }
+        private DateTime maxDateTime
+        {
+            get;
+            set;
+        }
+        private string copyStartTime
+        {
+            get;
+            set;
+        }
+
+        private string copyEndTime
+        {
+            get;
+            set;
+        }
+        private void button1_Click(object sender, EventArgs e)
+        {
+            Log.Info("点击复制该时间段的录音文件");
+            RecordingCopyJob(this.minDateTime, this.maxDateTime);
+        }
+        private void button2_Click(object sender, EventArgs e)
+        {
+            Log.Info("点击生成csv文件");
+            CreateCsvFileJob(this.minDateTime, this.maxDateTime);
+        }
+        private void Form1_Load(object sender, EventArgs e)
+        {
+            // 定时任务时间间隔为12小时
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["interval"]))
+            {
+                this.timer.Interval = (double)int.Parse(ConfigurationManager.AppSettings["interval"]);
+            }
+            // xml底层目录
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["xmlBasePath"]))
+            {
+                this.xmlBasePath = ConfigurationManager.AppSettings["xmlBasePath"];
+            }
+            // 复制xml底层目录
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["copyXmlFilePath"]))
+            {
+                this.copyXmlFilePath = ConfigurationManager.AppSettings["copyXmlFilePath"];
+            }
+            // 获取配置里的Oracle连接信息
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["default"]))
+            {
+                this.ConnectString = ConfigurationManager.AppSettings["default"];
+            }
+            // 获取配置里的Oracle连接信息
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["baseFilePath"]))
+            {
+                this.baseFilePath = ConfigurationManager.AppSettings["baseFilePath"];
+            }
+            // 获取csv存放路径
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["csvBaseFilePath"]))
+            {
+                this.csvBaseFilePath = ConfigurationManager.AppSettings["csvBaseFilePath"];
+            }
+        }
+
+        // xml解析方法并设置XmlModel属性
+        public static XmlModel XmlFileAnalysis(string filePath, XmlModel xmlModel)
+        {
+            Log.Info("开始分析" + filePath);
+            //这一步实例化一个xml命名空间管理器
+            XmlDocument doc = new XmlDocument();
+            doc.Load(filePath);
+            XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
+            nsMgr.AddNamespace("x", "http://www.verint.com/xmlns/recording20080320");
+
+            // 获取节点内容
+            XmlNode contacts = doc.SelectSingleNode("x:recording/x:contacts", nsMgr);
+            XmlNode contact = contacts.FirstChild;
+            if (contact != null)
+            {
+                XmlNode sessions = contact.SelectSingleNode("x:sessions", nsMgr);
+                XmlNode session = sessions.FirstChild;
+                XmlNode aniNode = session.SelectSingleNode("x:ani", nsMgr);
+                if (aniNode == null)
+                {
+                    return xmlModel;
+                }
+                // 主叫号码
+                string ani = aniNode.InnerText;
+                // 被叫号码
+                string dnis = session.SelectSingleNode("x:dnis", nsMgr).InnerText;
+                // 通话时长
+                string duration = session.SelectSingleNode("x:duration", nsMgr).InnerText;
+                // 录音流水ID
+                string parentinum = session.Attributes["x:parentinum"].Value;
+                // 通话拨打时间
+                string starttime = session.SelectSingleNode("x:starttime", nsMgr).InnerText;
+                starttime = SplitDateTimeString(starttime);
+                // 呼叫类型
+                string direction = session.SelectSingleNode("x:direction", nsMgr).InnerText;
+                // 录音流水ID
+                string switch_call_id = session.SelectSingleNode("x:switch_call_id", nsMgr).InnerText;
+
+                if ("Inbound".Equals(direction))
+                {
+                    direction = "0";
+                }
+                else
+                {
+                    direction = "1";
+                }
+                // 平台code
+                string switch_id = session.SelectSingleNode("x:switch_id", nsMgr).InnerText;
+                // 坐席ID
+                XmlNode sessionTags = session.SelectSingleNode("x:tags", nsMgr);
+                XmlNode sessionTag = sessionTags.FirstChild;
+                string agentid = "";
+                foreach (XmlNode xn1 in sessionTag)
+                {
+                    XmlElement xe1 = (XmlElement)xn1;
+                    if (xe1.GetAttribute("x:key").ToString() == "agentid")
+                    {
+                        agentid = xn1.InnerText;
+                        break;
+                    }
+                }
+                xmlModel.callerNumber = ani;
+                xmlModel.destinationNumber = dnis;
+                xmlModel.duration = duration;
+                xmlModel.dateStartCall = starttime;
+                xmlModel.callType = direction;
+                xmlModel.platformCode = switch_id;
+                xmlModel.agentId = agentid;
+                xmlModel.switch_call_id = switch_call_id;
+            }
+            // 通话结束时间
+            XmlNode tags = doc.SelectSingleNode("x:recording/x:segment/x:tags", nsMgr);
+            XmlNodeList tagList = tags.ChildNodes;
+            foreach (XmlNode xn in tagList)
+            {
+                XmlNode xn2 = xn.FirstChild;
+                string childAttributesValue = xn2.Attributes["x:key"].Value;
+                if ("endtime".Equals(childAttributesValue))
+                {
+                    string endtime = xn2.InnerText;
+                    endtime = SplitDateTimeString(endtime);
+                    xmlModel.dateHangup = endtime;
+                    break;
+                }
+            }
+            return xmlModel;
+        }
+        // 截取时间段
+        public static string SplitDateTimeString(string dateTimeString)
+        {
+            dateTimeString = dateTimeString.Substring(0, 19);
+            dateTimeString = dateTimeString.Replace("T", " ");
+            return dateTimeString;
+        }
+        // 获取文件MD5值方法
+        public static string getMD5ByMD5CryptoService(string path)
+        {
+            if (!File.Exists(path)) return "";
+            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
+            MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
+            byte[] buffer = md5Provider.ComputeHash(fs);
+            string resule = BitConverter.ToString(buffer);
+            md5Provider.Clear();
+            fs.Close();
+            return resule;
+        }
+        // 生成csv文件公共方法
+        private void CreateCsvFile(string filePath, List<string> lineList)
+        {
+            System.IO.FileInfo fi = new System.IO.FileInfo(filePath);
+            if (!fi.Directory.Exists)
+            {
+                fi.Directory.Create();  //文件不存在,创建文件
+            }
+
+            System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
+            System.IO.StreamWriter sw = new System.IO.StreamWriter(fs, Encoding.Default);
+            // 循环列数组  写入表数据
+            foreach (string line in lineList)
+            {
+                sw.WriteLine(line);
+            }
+            sw.Close();
+            fs.Close();
+        }
+        // 生成csv文件定时任务
+        private void CreateCsvFileJob(DateTime minTime, DateTime maxTime)
+        {
+            Log.Debug("开始生成csv文件任务");
+            // 定义表数组    
+            List<string> lineList = new List<string>();
+            // 定义表头
+            lineList.Add("录音流水ID,录音文件名,数据包,通话时长(单位:秒),通话拨打时间,通话挂机时间,主叫号码,被叫号码,坐席工号,坐席ID,质检场景,呼叫类型(0:呼入,1:呼出),客户号,平台code,扩展字段1,扩展字段2,扩展字段3,扩展字段4,扩展字段5,扩展字段6");
+            OracleHelper oracleHelper = null;
+            DataTable dataList = new DataTable();
+            try
+            {
+                oracleHelper = new OracleHelper(this.ConnectString);
+                dataList = getSqlField(oracleHelper, minTime, maxTime);
+                oracleHelper = null;
+            }
+            catch (Exception exp)
+            {
+                Log.Debug(exp);
+            }
+            finally
+            {
+                bool flag = oracleHelper != null;
+                if (flag)
+                {
+                    oracleHelper.CloseConnection();
+                    oracleHelper = null;
+                }
+            }
+            // 获取录音流水文件List
+            string lastTimeFileName = this.baseFilePath + "\\lastTimeFileName.txt";
+            Log.Debug("获取上次分析路径为:" + lastTimeFileName);
+            List<string> filePathList = new List<string>();
+            // 判断文件是否存在
+            if (File.Exists(lastTimeFileName))
+            {
+                
+                string catalog = File.ReadAllText(lastTimeFileName);
+                Log.Debug("成功获取上次记录:" + catalog);
+                // 上一次copy文件夹的目录级别
+                string[] catalogList = catalog.Split('\\');
+                int catalogListSize = catalogList.Length;
+                string level1Catalog = catalogList[catalogListSize - 3];
+                string level2Catalog = catalogList[catalogListSize - 2];
+                string level3Catalog = catalogList[catalogListSize - 1];
+                for (int i = int.Parse(level1Catalog); i <= 99; i++)
+                {
+                    
+                    string level1Dir = this.copyXmlFilePath + "\\" + i.ToString().PadLeft(3, '0');
+                    Log.Debug("判断文件夹路径是否存在" + level1Dir);
+                    // 判断文件夹路径是否存在 不存在则结束循环
+                    if (!Directory.Exists(level1Dir))
+                    {
+                        break;
+                    }
+                    for (int j = i == int.Parse(level1Catalog) ? int.Parse(level2Catalog) : 0; j <= 99; j++)
+                    {
+                        string level2Dir = level1Dir + "\\" + j.ToString().PadLeft(2, '0');
+                        Log.Debug("判断文件夹路径是否存在" + level2Dir);
+                        // 判断文件夹路径是否存在 不存在则结束循环
+                        if (!Directory.Exists(level2Dir))
+                        {
+                            break;
+                        }
+                        for (int k = j == int.Parse(level2Catalog) ? int.Parse(level3Catalog) : 0; k <= 99; k++)
+                        {
+                            
+                            string level3Dir = level2Dir + "\\" + k.ToString().PadLeft(2, '0');
+                            Log.Debug("判断文件夹路径是否存在" + level3Dir);
+                            // 判断文件夹路径是否存在 不存在则结束循环
+                            if (!Directory.Exists(level3Dir))
+                            {
+                                break;
+                            }
+                            filePathList = GetDirectories(level3Dir, filePathList);
+                            string filePathString = string.Join(",", filePathList);
+                            Log.Debug("扫描到的文件列表为:" + filePathString);
+                        }
+                    }
+                }
+            }
+            // 获取当前日期格式
+            string nowDate = maxTime.AddHours(-1).ToString("yyyy-MM-dd");
+            string newFilePath = this.csvBaseFilePath + "\\" + nowDate;
+
+            // 最后一个文件名
+            string lastFileName = "";
+
+            if (dataList != null && dataList.Rows.Count > 0)
+            {
+                foreach (string path in filePathList)
+                {
+                    // 获取录音文件信息
+                    FileInfo xmlFile = new FileInfo(path);
+                    string extension = Path.GetExtension(path);
+                    if (".xml".Equals(extension))
+                    {
+                        // 设置xmlModel属性
+                        XmlModel xmlModel = new XmlModel();
+                        XmlFileAnalysis(path, xmlModel);
+                        string switchCallId = xmlModel.switch_call_id;
+                        if (switchCallId != null)
+                        {
+                            DataRow[] row = dataList.Select("callid = " + xmlModel.switch_call_id);
+                            if (row.Length > 0)
+                            {
+                                //拷贝到csv当天目录下
+                                string wavPath = path.Replace("xml", "wav");
+                                CopyToFile(wavPath, newFilePath);
+                                DataRow dr = row[0];
+                                // 获取录音ID   
+                                string recordingId = dr[0].ToString();
+                                // 获取质检场景
+                                string caltype = dr[1].ToString();
+                                caltype = caltype.Replace("-", "_");
+                                int index = caltype.IndexOf("(");
+                                if (index >= 0)
+                                {
+                                    caltype = caltype.Substring(0, index);
+                                }
+                                // 获取入司时间
+                                string employedDate = dr[2].ToString();
+                                // 获取组别
+                                string title = dr[3].ToString();
+                                // 客户评价
+                                string evaluation = dr[4].ToString();
+                                // 客户等级
+                                string level = dr[5].ToString();
+                                // 客户类别
+                                string category = dr[6].ToString();
+                                // 坐席工号
+                                string staffname = dr[7].ToString();
+                                // 坐席ID
+                                string agent_id = dr[8].ToString();
+                                // 业务号
+                                string remark6 = dr[9].ToString();
+
+                                xmlModel.recordingId = recordingId;
+                                xmlModel.recordingFileName = Path.GetFileNameWithoutExtension(path) + ".wav";
+                                xmlModel.sceneName = caltype;
+                                xmlModel.remark1 = employedDate;
+                                xmlModel.remark2 = title;
+                                xmlModel.remark3 = evaluation;
+                                xmlModel.remark4 = level;
+                                xmlModel.remark5 = category;
+                                xmlModel.agentCti = staffname;
+                                xmlModel.agentId = agent_id;
+                                xmlModel.remark6 = remark6;
+
+                                lastFileName = Path.GetFileNameWithoutExtension(path) + ".wav";
+                                // 定义列字符串
+                                string lineString = "";
+                                // 遍历对象属性赋值拼接字符串
+                                foreach (System.Reflection.PropertyInfo p in xmlModel.GetType().GetProperties())
+                                {
+                                    lineString += p.GetValue(xmlModel);
+                                    lineString += ",";
+                                }
+                                lineString = lineString.Remove(lineString.LastIndexOf(","));
+                                lineString = lineString.Remove(lineString.LastIndexOf(","));
+                                lineList.Add(lineString);
+                            }
+                        }
+                    }
+                }
+            }
+            string filePath = newFilePath + "\\" + maxTime.ToString("yyyy-MM-ddHH") + ".csv";  //文件路径
+            CreateCsvFile(filePath, lineList);
+            // 获取最后一个文件目录完成csv生成之后将最后一个文件所在目录缓存进文件
+            if (!string.IsNullOrEmpty(lastFileName))
+            {
+                string directory1 = lastFileName.Substring(6, 3);
+                string directory2 = lastFileName.Substring(9, 2);
+                string directory3 = lastFileName.Substring(11, 2);
+                string lastFilePath = this.copyXmlFilePath + "\\" + directory1 + "\\" + directory2 + "\\" + directory3;
+                string path = this.baseFilePath + "\\lastTimeFileName.txt";
+                if (File.Exists(path))
+                {
+                    File.Delete(path);
+                }
+                File.AppendAllText(path, lastFilePath);
+            }
+        }
+        // 拷贝文件到另一个文件夹下
+        // <param name="sourceName">源文件路径</param>
+        // <param name="folderPath">目标路径(目标文件夹)</param>
+        private void CopyToFile(string sourceName, string folderPath)
+        {
+            if (!Directory.Exists(folderPath))
+            {
+                Directory.CreateDirectory(folderPath);
+            }
+            //当前文件如果不用新的文件名,那么就用原文件文件名
+            string fileName = Path.GetFileName(sourceName);
+            //这里可以给文件换个新名字,如下:
+            //string fileName = string.Format("{0}.{1}", "newFileText", "txt");
+
+            //目标整体路径
+            string targetPath = Path.Combine(folderPath, fileName);
+
+            //Copy到新文件下
+            FileInfo file = new FileInfo(sourceName);
+            if (file.Exists)
+            {
+                //true 为覆盖已存在的同名文件,false 为不覆盖
+                file.CopyTo(targetPath, true);
+            }
+        }
+
+        private void CopyToFile(string sourceName, string folderPath, string newFileName)
+        {
+            if (!Directory.Exists(folderPath))
+            {
+                Directory.CreateDirectory(folderPath);
+            }
+            //这里可以给文件换个新名字,如下:
+            //目标整体路径
+            string targetPath = Path.Combine(folderPath, newFileName);
+
+            //Copy到新文件下
+            FileInfo file = new FileInfo(sourceName);
+            if (file.Exists)
+            {
+                //true 为覆盖已存在的同名文件,false 为不覆盖
+                file.CopyTo(targetPath, true);
+            }
+        }
+        // 时间检测 定时任务
+        public void OnTimer(object sender, ElapsedEventArgs args)
+        {
+            // 时间等于12:00  执行中午的录音拷贝
+            if (DateTime.Now.Hour == 12 && DateTime.Now.Minute == 15)
+            {
+                // 当天0时0分0秒:
+                minDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                // 当天12:00
+                maxDateTime = minDateTime.AddHours(12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "录音文件拷贝任务");
+                // 调用录音拷贝任务
+                RecordingCopyJob(minDateTime, maxDateTime);
+            }
+            // 时间等于12: 00  执行中午的生成csv文件
+            else if (DateTime.Now.Hour == 12 && DateTime.Now.Minute == 30)
+            {
+                // 当天0时0分0秒:
+                minDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                // 当天12:00
+                maxDateTime = minDateTime.AddHours(12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "的生成csv文件任务");
+                CreateCsvFileJob(minDateTime, maxDateTime);
+            }
+            // 时间等于00:00 执行下午的录音拷贝
+            else if (DateTime.Now.Hour == 00 && DateTime.Now.Minute == 15)
+            {
+
+                maxDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                minDateTime = maxDateTime.AddHours(-12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "录音文件拷贝任务");
+                RecordingCopyJob(minDateTime, maxDateTime);
+            }
+            // 时间等于00:30 执行下午的生成csv文件
+            else if (DateTime.Now.Hour == 0 && DateTime.Now.Minute == 30)
+            {
+                maxDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                minDateTime = maxDateTime.AddHours(-12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "的生成csv文件任务");
+                CreateCsvFileJob(minDateTime, maxDateTime);
+            }
+        }
+
+        // 录音拷贝任务
+        public void RecordingCopyJob(DateTime minTime, DateTime maxTime)
+        {
+            Log.Debug("开始录音拷贝处理");
+            // 定义文件路径列表
+            List<string> list = new List<string>();
+            // 获取某文件夹里最新的文件夹
+            string path = this.baseFilePath + "\\lastTimeFileName.txt";
+            Log.Debug("获取上次拷贝地址为:" + path);
+            // 判断文件是否存在
+            if (File.Exists(path))
+            {
+                Log.Debug("成功获取上次记录:" + path);
+                string catalog = File.ReadAllText(path);
+                // 上一次copy文件夹的目录级别
+                string[] catalogList = catalog.Split('\\');
+                int catalogListSize = catalogList.Length;
+                string level1Catalog = catalogList[catalogListSize - 3];
+                string level2Catalog = catalogList[catalogListSize - 2];
+                string level3Catalog = catalogList[catalogListSize - 1];
+                if (level3Catalog == "00")
+                {
+                    level3Catalog = "99";
+                    if (level2Catalog == "00")
+                    {
+                        level2Catalog = "99";
+                        level1Catalog = (int.Parse(level1Catalog) - 1).ToString().PadLeft(3, '0');
+                    }
+                    else
+                    {
+                        level2Catalog = (int.Parse(level2Catalog) - 1).ToString().PadLeft(2, '0');
+                    }
+                }
+                else
+                {
+                    level3Catalog = (int.Parse(level3Catalog) - 1).ToString().PadLeft(2, '0');
+                }
+
+                // 获取文件夹内的最新文件夹(max:一级目录,max2:二级目录,max3:三级目录)
+                FtpHelper ftpHelper = new FtpHelper();
+                List<string> dirctoryList = ftpHelper.GetDirctory(this.xmlBasePath);
+                int max = getMaxNumber(dirctoryList);
+                int max2 = 0;
+                int max3 = 0;
+                // 循环获取对象中的文件路径
+                for (int i = int.Parse(level1Catalog); i <= max; i++)
+                {
+                    string path2 = this.xmlBasePath + i.ToString().PadLeft(3, '0') + "/";
+                    string copyPath2 = this.copyXmlFilePath + "\\" + i.ToString().PadLeft(3, '0');
+                    string path3 = "";
+                    string copyPath3 = "";
+                    string path4 = "";
+                    string copyPath4 = "";
+                    List<string> dirctoryList2 = ftpHelper.GetDirctory(path2);
+                    max2 = getMaxNumber(dirctoryList2);
+                    Log.Debug("i:"+i+ "|level1Catalog:"+ int.Parse(level1Catalog));
+                    if (i > int.Parse(level1Catalog))
+                    {
+                        level2Catalog = "0";
+                        level3Catalog = "0";
+                    }
+                    for (int j = int.Parse(level2Catalog); j <= max2; j++)
+                    {
+                        path3 = path2 + j.ToString().PadLeft(2, '0') + "/";
+                        copyPath3 = copyPath2 + "\\" + j.ToString().PadLeft(2, '0');
+                        ftpHelper.GetDirctory(path3);
+                        List<string> dirctoryList3 = ftpHelper.GetDirctory(path3);
+                        max3 = getMaxNumber(dirctoryList3);
+                        if (j > int.Parse(level2Catalog))
+                        {
+                            level3Catalog = "0";
+                        }
+                        Log.Debug("secondCatalog:" + path3 + "|max3:" + max3 + "|level3Catalog:" + level3Catalog);
+                        for (int l = int.Parse(level3Catalog); l <= max3; l++)
+                        {
+                            path4 = path3 + l.ToString().PadLeft(2, '0') + "/";
+                            copyPath4 = copyPath3 + "\\" + l.ToString().PadLeft(2, '0');
+                            Log.Info("开始从" + path4 + "复制录音文件");
+                            ftpHelper.DownFtp(path4, copyPath4);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                List<string> filePathList = new List<string>();
+                FtpHelper ftpHelper = new FtpHelper();
+                ftpHelper.DownFtp(this.xmlBasePath, this.copyXmlFilePath);
+            }
+
+        }
+        // 获取当前路径下数量最大的文件夹名称
+        public int getMaxNumberDirectories(string path)
+        {
+            DirectoryInfo d = new DirectoryInfo(path);
+            DirectoryInfo[] directs = d.GetDirectories();//文件夹
+            int max = 0;
+            foreach (DirectoryInfo dd in directs)
+            {
+                int temp = int.Parse(dd.Name);
+                if (temp > max)
+                {
+                    max = temp;
+                }
+            }
+
+            return max;
+        }
+        // 获取当前路径下数量最大的文件夹名称
+        public int getMaxNumber(List<string> numberList)
+        {
+            int max = 0;
+            foreach (string number in numberList)
+            {
+                int temp = int.Parse(number);
+                if (temp > max)
+                {
+                    max = temp;
+                }
+            }
+            return max;
+        }
+        // 获取文件夹名
+        public List<string> GetDirectories(string dir, List<string> list)
+        {
+            DirectoryInfo d = new DirectoryInfo(dir);
+            FileInfo[] files = d.GetFiles();//文件
+            DirectoryInfo[] directs = d.GetDirectories();//文件夹
+            foreach (FileInfo f in files)
+            {
+                list.Add(f.FullName);//添加文件名到列表中  
+            }
+            //获取子文件夹内的文件列表,递归遍历  
+            foreach (DirectoryInfo dd in directs)
+            {
+                GetDirectories(dd.FullName, list);
+            }
+            return list;
+        }
+        /// <summary>
+        /// 将制定目录下的文件压缩为tar文件
+        /// </summary>
+        /// <param name="IN">源目录D:\\Images</param>
+        /// <param name="OUT">目标目录tar文件F:\\tar\\aaa.tar</param>
+        public static void CompressTarFile(string IN, string OUT)
+        {
+            Stream outStream = new FileStream(OUT, FileMode.OpenOrCreate);
+            TarArchive archive = TarArchive.CreateOutputTarArchive(outStream, TarBuffer.DefaultBlockFactor);
+            String[] files = Directory.GetFiles(IN);
+            foreach (String name in files)
+            {
+                TarEntry entry = TarEntry.CreateEntryFromFile(name);
+                entry.Name = name.Substring(name.LastIndexOf('\\') + 1);
+                archive.WriteEntry(entry, true);
+            }
+            if (archive != null)
+            {
+                archive.CloseArchive();
+            }
+        }
+        private DataTable getSqlField(OracleHelper oradb, DateTime minTime, DateTime maxTime)
+        {
+            string sql = string.Format("select r.recordno ID," +
+                "case when s3.workordertype3desc is null and s2.workordertype2desc is not null then s1.workordertype1desc || '_' || s2.workordertype2desc "+
+                "when s3.workordertype3desc is null and s2.workordertype2desc is null then substr(caltype, instr(caltype, '-', 1, 2) + 1, instr(caltype, '(') - 9) "+
+                "when ec.CALLNATUREGROUP_ID = 'FWF7RO' and e.calltype = '1' then substr(caltype, instr(caltype, '-', 1, 2) + 1, instr(caltype, '(') - 9)  "+
+                "else s1.workordertype1desc || '_' || s2.workordertype2desc || '_' || s3.workordertype3desc end 质检场景,"+
+                "case when s.employeddate is null then '无入司时间'" +
+                "when floor(months_between(sysdate,s.employeddate)) >=0 and floor(months_between(sysdate,s.employeddate))< 3 then '三个月以内'" +
+                "when floor(months_between(sysdate,s.employeddate)) >=6 and floor(months_between(sysdate,s.employeddate))< 12 then '半年到一年'" +
+                "when floor(months_between(sysdate,s.employeddate)) >=12 and floor(months_between(sysdate,s.employeddate))< 24 then '一年到两年'" +
+                "else '两年及以上' end   入司时间,s.title 组别,decode(w.statisfaction1,'1','非常满意','2','满意','3','不满意','4','非常不满意','') 客户评价,c.fax 客户等级,c.homepage 客户类别," +
+                "s.staffname 坐席工号,s.agent_id 坐席id,t.businessno 业务号,r.initcallid callid from callcenter.record r " +
+                "left join callcenter.event e on e.event_guid = r.event_guid " +
+                "left join callcenter.tabccalsum t on t.relation_id = r.event_guid " +
+                "left join (select wm.event_guid,wm.statisfaction1,row_number() over(partition by wm.event_guid order by createddate) rn from wmsk_statisfaction wm) w on e.event_guid=w.event_guid " +
+                "left join callcenter.staff s on r.staff_id = s.staff_id " +
+                "left join callcenter.customer c on r.customer_guid = c.customer_guid " +
+                "left join callcenter.eventcallnature ec on ec.event_guid = r.event_guid " +
+                "left join callcenter.sys_workordertype1 s1 on s1.workordertype1_id = ec.callnaturegroup_id " +
+                "left join callcenter.sys_workordertype2 s2 on s2.workordertype2_id = ec.callnature_id " +
+                "left join callcenter.sys_workordertype3 s3 on s3.workordertype3_id = ec.callnature3_id " +
+                "left join callcenter.sys_workordertype4 s4 on s4.workordertype4_id = ec.callnature4_id " +
+                "left join callcenter.custom_parameter cp1 on cp1.parameter_id = t.producttype and cp1.parameter_type = 'producttype' " +
+                "where (w.rn=1 or w.rn is null) and " +
+                "r.starttime>=to_date('{0}','yyyy-mm-dd hh24:mi:ss') " +
+                "and r.starttime <= to_date('{1}','yyyy-mm-dd hh24:mi:ss')", minTime.ToString(), maxTime.ToString());
+            //string sql = string.Format("select * from TEST2");
+            DataTable data = oradb.GetDataTable(sql);
+            string idString = "";
+            for (int i = 0; i < data.Rows.Count; i++)
+            {
+                idString = idString + data.Rows[i]["callid"].ToString() + ",";//行集合.行【号】列【名】
+            }
+            Log.Debug("sql查询结果11为:" + idString);
+            return data;
+        }
+
+        public static string DeleteOneFile(string fileFullPath)
+        {
+            // 1、首先判断文件或者文件路径是否存在
+            if (Directory.Exists(fileFullPath))
+            {
+                // 2、根据路径字符串判断是文件还是文件夹
+                FileAttributes attr = File.GetAttributes(fileFullPath);
+                // 3、根据具体类型进行删除
+                if (attr == FileAttributes.Directory)
+                {
+                    Directory.Delete(fileFullPath, true); // 3.1、删除文件夹
+                }
+                else
+                {
+                    File.Delete(fileFullPath);// 3.2、删除文件
+                }
+                File.Delete(fileFullPath);
+                return "删除成功:" + fileFullPath;
+            }
+            return "无该文件或文件夹:" + fileFullPath;
+        }
+
+        private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
+        {
+            this.minDateTime = this.dateTimePicker1.Value;
+        }
+
+        private void dateTimePicker2_ValueChanged(object sender, EventArgs e)
+        {
+            this.maxDateTime = this.dateTimePicker2.Value;
+        }
+
+        private void button3_Click(object sender, EventArgs e)
+        {
+            Log.Debug("手动执行" + DateTime.Now.Hour + "清理过期录音文件任务");
+            CleanCsvRecardFile(this.copyXmlFilePath, 8);
+            CleanCsvRecardFile(this.csvBaseFilePath, 8);
+        }
+
+        // 删除某文件下超过days天的文件并且保留csv文件
+        public static void CleanCsvRecardFile(string folderPath, int days)
+        {
+            // 获取当前日期和时间
+            DateTime currentDate = DateTime.Now;
+
+            // 遍历文件夹中的所有文件
+            string[] files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);
+            foreach (string file in files)
+            {
+                // 获取文件最后写入时间
+                DateTime lastWriteTime = File.GetLastWriteTime(file);
+
+                // 获取文件拓展名
+                String fileExtension = Path.GetExtension(file);
+
+                // 计算最后写入时间与当前时间的差值
+                TimeSpan timeDifference = currentDate - lastWriteTime;
+
+                // 如果差值大于指定天数,则删除文件
+                if (timeDifference.TotalDays > days && fileExtension != ".csv")
+                {
+                    File.Delete(file);
+                    Console.WriteLine("Deleted file: " + file);
+                }
+            }
+        }
+    }
+}

+ 120 - 0
XmlDocumentAnalysis/Form1.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 185 - 0
XmlDocumentAnalysis/FtpHelper.cs

@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XmlDucumentAnalysis
+{
+    public class FtpHelper
+    {
+
+        /// <summary>
+        /// 初始ftp路径
+        /// </summary>
+        public static string initFtpPath = ConfigurationManager.AppSettings["xmlBasePath"];
+
+
+
+        /// <summary>  
+        /// 单个文件下载方法  
+        /// </summary>  
+        /// <param name="localPath">保存文件的本地路径</param>  
+        /// <param name="ftpPath">下载文件的FTP路径</param>  
+        public void Download(string ftpPath, string localSavePath)
+        {
+            try
+            {
+                //FileMode常数确定如何打开或创建文件,指定操作系统应创建新文件。  
+                //FileMode.Create如果文件已存在,它将被改写  
+                string fileName = ftpPath.Substring(ftpPath.LastIndexOf("/")+1);
+                string downloadFilePath = Path.Combine(localSavePath, fileName);  // Replace "file.txt" with the actual file name
+                FileStream fs = new FileStream(downloadFilePath, FileMode.Create);
+                FtpWebRequest downRequest = (FtpWebRequest)WebRequest.Create(new Uri(ftpPath));
+                //设置要发送到 FTP 服务器的命令  
+                downRequest.Method = WebRequestMethods.Ftp.DownloadFile;
+                FtpWebResponse response = (FtpWebResponse)downRequest.GetResponse();
+                Stream ftpStream = response.GetResponseStream();
+                long cl = response.ContentLength;
+                int bufferSize = 2048;
+                int readCount;
+                byte[] buffer = new byte[bufferSize];
+                readCount = ftpStream.Read(buffer, 0, bufferSize);
+                while (readCount > 0)
+                {
+                    fs.Write(buffer, 0, readCount);
+                    readCount = ftpStream.Read(buffer, 0, bufferSize);
+                }
+                ftpStream.Close();
+                fs.Close();
+                response.Close();
+            }
+            catch (Exception ee)
+            {
+                Console.WriteLine("Download方法异常:" + ee.ToString());
+            }
+        }
+
+
+        /// <summary>
+        /// 整个文件夹的文件及子目录 下载方法
+        /// </summary>
+        /// <param name="ftpPath">FTP路径</param>
+        /// <param name="localSavePath">保存的本地路径</param>
+        public void DownFtp(string ftpPath, string localSavePath)
+        {
+            try
+            {
+
+                string downloadDir = localSavePath;
+                string ftpdir = ftpPath;
+                List<string> fullname = GetDirctory(ftpdir);
+                // 如果不存在 则创建新的目录
+                if (!Directory.Exists(downloadDir))
+                {
+                    Directory.CreateDirectory(downloadDir);
+                }
+                if (fullname == null || fullname.Count == 0)
+                {
+                    return;
+                }
+                foreach (string names in fullname)
+                {
+                    if (names.Trim() == "")
+                    {
+                        continue;
+                    }
+                    //判断是否具有文件夹标识<DIR>或者names的首字符是d  (两者均表示此路径是文件夹而非文件)
+                    if (!names.Contains("."))
+                    {
+                        DownFtp(ftpdir + names + "/", downloadDir + "\\" + names);
+                    }
+                    else
+                    {
+                        string fileFullName = ftpdir + names;
+                        //在本地查找是否已存在此文件,若已存在,则不再下载
+                        if (File.Exists(localSavePath+"\\"+names))
+                        {
+                            Log.Info(names+"已存在");
+                        }
+                        Download(fileFullName, downloadDir);
+                    }
+
+                }
+            }
+            catch (Exception ee)
+            {
+                Console.WriteLine("异常信息:" + ee.ToString());
+            }
+        }
+        /// 清空指定的文件夹(包括子目录文件夹),但不删除文件夹  
+        /// </summary>  
+        /// <param name="dir">指定目录</param>  
+        public static void DeleteFolder(string dir)
+        {
+            foreach (string d in Directory.GetFileSystemEntries(dir))
+            {
+                if (System.IO.File.Exists(d))
+                {
+                    FileInfo fi = new FileInfo(d);
+                    if (fi.Attributes.ToString().IndexOf("ReadOnly") != -1)
+                        fi.Attributes = FileAttributes.Normal;
+                    System.IO.File.Delete(d);//直接删除其中的文件    
+                }
+                else
+                {
+                    DirectoryInfo d1 = new DirectoryInfo(d);
+                    if (d1.GetFiles().Length != 0 || d1.GetDirectories().Length != 0)
+                    {
+                        DeleteFolder(d1.FullName); // 递归删除子文件夹
+                    }
+                    Directory.Delete(d);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 从ftp服务器上获得文件夹列表
+        /// </summary>
+        /// <param name="RequedstPath">服务器下的相对路径</param>
+        /// <returns></returns>
+        public List<string> GetDirctory(string RequedstPath)
+        {
+            Log.Debug("开始获取"+RequedstPath+"列表");
+            List<string> strs = new List<string>();
+            try
+            {
+                string uri = RequedstPath;   //目标路径 path为服务器地址
+                FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
+                // ftp用户名和密码
+                reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
+                WebResponse response = reqFTP.GetResponse();
+                StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名
+                string line = reader.ReadLine();
+                while (line != null)
+                {   
+                    string temp = line.Substring(line.LastIndexOf(" ")+1);
+                    string temp1 = line.Substring(0, 1);
+                    if (line.Contains("<DIR>"))
+                    {
+                        string msg = line.Substring(line.LastIndexOf("<DIR>") + 5).Trim();
+                        strs.Add(msg);
+                    } else if (temp1.Equals("d") && temp!="." && temp!="..")
+                    {
+                        strs.Add(temp);
+                    }else if (!temp1.Equals("d"))
+                    {
+                        strs.Add(temp);
+                    }
+                    line = reader.ReadLine();
+                }
+                reader.Close();
+                response.Close();
+                return strs;
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine("获取目录出错:" + ex.Message);
+            }
+            return strs;
+        }
+    }
+}

+ 329 - 0
XmlDocumentAnalysis/Log.cs

@@ -0,0 +1,329 @@
+using System;
+using System.Collections.Generic;
+using log4net;
+using log4net.Config;
+using System.IO;
+using System.Reflection;
+using System.Web;
+
+namespace XmlDucumentAnalysis
+{
+    /// <summary>
+    /// log4net封装类
+    /// </summary>
+    public class Log
+    {
+        #region 静态变量
+        private const string DEFAULTLOGGERNAME = "ApplicationInfoLog";
+        private static string LOGCONFIG = "log4net.config";//log4net配置文件名
+        private static Dictionary<string, ILog> dicLogger = new Dictionary<string, ILog>();
+        #endregion
+
+        #region 静态构造函数
+
+        static Log()
+        {
+            //设置log4net配置文件
+            if (File.Exists(Log4NetConfigFile))
+            {
+                if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+                {
+                    XmlConfigurator.ConfigureAndWatch(new FileInfo(Log4NetConfigFile));
+                }
+                else
+                {
+                    XmlConfigurator.Configure(new FileInfo(Log4NetConfigFile));
+                }
+            }
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 配置文件路径
+        /// </summary>
+        public static string Log4NetConfigFile
+        {
+            get
+            {
+                //if (System.Web.HttpContext.Current != null)
+                //    return Path.Combine(System.Web.HttpContext.Current.Request.PhysicalApplicationPath, LOGCONFIG);
+                //else
+                return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), LOGCONFIG);
+            }
+        }
+
+        #region Fatal
+        /// <summary>
+        /// 记录一个程序致命性错误
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="exp"></param>
+        public static void Fatal(string message, Exception exp)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsFatalEnabled)
+                {
+                    Logger.Fatal(message, exp);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Fatal() failed on logging '{0}'", message + "::" + exp.Message));
+            }
+        }
+
+        /// <summary>
+        /// 记录一个程序致命性错误
+        /// </summary>
+        /// <param name="message"></param>
+        public static void Fatal(string message)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsFatalEnabled)
+                {
+                    Logger.Fatal(message);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Fatal() failed on logging '{0}'", message), e);
+            }
+        }
+        #endregion
+
+        #region Error
+        /// <summary>
+        /// 记录一个错误信息
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="exp"></param>
+        public static void Error(string message, Exception exp)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsErrorEnabled)
+                {
+                    Logger.Error(message, exp);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Error() failed on logging '{0}'", message + "::" + exp.Message));
+            }
+        }
+
+        /// <summary>
+        /// 记录一个错误信息
+        /// </summary>
+        /// <param name="message"></param>
+        public static void Error(string message)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsErrorEnabled)
+                {
+                    Logger.Error(message);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Error() failed on logging '{0}'", message), e);
+            }
+        }
+        #endregion
+
+        #region Warn
+        /// <summary>
+        /// 记录一个警告信息
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="exp"></param>
+        public static void Warn(string message, Exception exp)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsWarnEnabled)
+                {
+                    Logger.Warn(message, exp);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Warn() failed on logging '{0}'", message + "::" + exp.Message));
+            }
+        }
+
+        /// <summary>
+        /// 记录一个警告信息
+        /// </summary>
+        /// <param name="message"></param>
+        public static void Warn(string message)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsWarnEnabled)
+                {
+                    Logger.Warn(message);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Warn() failed on logging '{0}'", message), e);
+            }
+        }
+        #endregion
+
+        #region Info
+        /// <summary>
+        /// 记录信息
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="exp"></param>
+        public static void Info(string message, Exception exp)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsInfoEnabled)
+                {
+                    Logger.Info(message, exp);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Info() failed on logging '{0}'", message + "::" + exp.Message));
+            }
+        }
+
+        /// <summary>
+        /// 记录信息
+        /// </summary>
+        /// <param name="message"></param>
+        public static void Info(string message)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsInfoEnabled)
+                {
+                    Logger.Info(message);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Info() failed on logging '{0}'", message), e);
+            }
+        }
+        #endregion
+
+        #region Debug
+        /// <summary>
+        /// 记录调试信息
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="exp"></param>
+        public static void Debug(string message, Exception exp)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsDebugEnabled)
+                {
+                    Logger.Debug(message, exp);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Debug() failed on logging '{0}'", message + "::" + exp.Message));
+            }
+        }
+
+        /// <summary>
+        /// 记录调试信息
+        /// </summary>
+        /// <param name="message"></param>
+        public static void Debug(string message)
+        {
+            Debug(message, DEFAULTLOGGERNAME);
+        }
+
+        /// <summary>
+        /// 记录调试信息
+        /// </summary>
+        /// <param name="message">信息内容</param>
+        /// <param name="LoggerName"></param>
+        public static void Debug(string message, string LoggerName)
+        {
+            if (HttpContext.Current != null)
+                message = System.Web.HttpContext.Current.Request.Url.ToString() + "\r\n" + message;
+
+            ILog Logger = GetLogger(LoggerName);
+
+            try
+            {
+                if (Logger.IsDebugEnabled)
+                {
+                    Logger.Debug(message);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Debug() failed on logging '{0}'", message), e);
+            }
+        }
+
+        /// <summary>
+        /// 记录调试信息
+        /// </summary>
+        /// <param name="message"></param>
+        public static void Debug(Exception exp)
+        {
+            ILog Logger = GetLogger();
+            try
+            {
+                if (Logger.IsDebugEnabled)
+                {
+                    Logger.Debug(exp);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ApplicationException(string.Format("Logger.Debug() failed on logging '{0}'", exp.Message));
+            }
+        }
+        #endregion
+
+        #region 其他
+        /// <summary>
+        /// 获取实现ILog接口实例
+        /// </summary>
+        /// <returns></returns>
+        public static ILog GetLogger()
+        {
+            return GetLogger(DEFAULTLOGGERNAME);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="LoggerName"></param>
+        /// <returns></returns>
+        public static ILog GetLogger(string LoggerName)
+        {
+            if (!dicLogger.ContainsKey(LoggerName))
+                dicLogger.Add(LoggerName, LogManager.GetLogger(LoggerName));
+            return dicLogger[LoggerName];
+        }
+        #endregion
+
+    }
+}

+ 32 - 0
XmlDocumentAnalysis/Log4net.config

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+  <!-- This section contains the log4net configuration settings -->
+  <log4net>
+    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
+      <!--日志文件路径-->
+      <file value="Log/" />
+      <!--是否是向文件中追加日志-->
+      <appendToFile value="true" />
+      <rollingStyle value="Composite" />
+      <!--日志文件名是否是固定不变的-->
+      <staticLogFileName value="false" />
+      <!--日志文件名格式为:20200220.log-->
+      <datePattern value="yyyyMMdd'.log'" />
+      <!--log保留天数-->
+      <maxSizeRollBackups value="10" />
+      <!--最大文件大小-->
+      <maximumFileSize value="20MB" />
+      <!--信息日志布局-->
+      <layout type="log4net.Layout.PatternLayout">
+        <conversionPattern value="%date  [%thread]  %-5level  %message%newline" />
+      </layout>
+    </appender>
+
+    <!-- Setup the root category, add the appenders and set the default level -->
+    <root>
+      <level value="ALL" />
+      <appender-ref ref="RollingLogFileAppender" />
+    </root>
+
+  </log4net>
+</configuration>

+ 434 - 0
XmlDocumentAnalysis/OracleHelper.cs

@@ -0,0 +1,434 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.OracleClient;
+using XmlDucumentAnalysis;
+
+namespace DataPumpWindowsService
+{
+    public class OracleHelper
+    {
+        private string _message = "";//返回信息
+        public OracleConnection _con_SQL;//连接对象
+
+        public string Message { get { return _message; } }
+
+        public OracleHelper(string connecteString)
+        {
+            _con_SQL = new OracleConnection(connecteString);
+        }
+
+        #region 命令、事务、连接
+        /// <summary>
+        /// 创建命令对象
+        /// </summary>
+        /// <returns></returns>
+        private OracleCommand CreateCommand()
+        {
+            OracleCommand cmdObj = _con_SQL.CreateCommand();
+            cmdObj.CommandTimeout = int.MaxValue;
+            return cmdObj;
+        }
+
+        /// <summary>
+        /// 打开连接
+        /// </summary>
+        /// <returns></returns>
+        public bool OpenConnection()
+        {
+            //检测连接是否已打开
+            if (_con_SQL.State == System.Data.ConnectionState.Open)
+                return true;
+            try
+            {
+                _con_SQL.Open();
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                return false;
+            }
+
+            //检测连接状态
+            if (_con_SQL.State != System.Data.ConnectionState.Open)
+            {
+                _message = "打开连接失败";
+                return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 关闭连接
+        /// </summary>
+        /// <returns></returns>
+        public bool CloseConnection()
+        {
+            if (_con_SQL.State == System.Data.ConnectionState.Closed)
+                return true;
+
+            try
+            {
+                _con_SQL.Close();
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                return false;
+            }
+
+            if (_con_SQL.State != System.Data.ConnectionState.Closed)
+            {
+                _message = "关闭连接失败";
+                return false;
+            }
+            return true;
+        }
+        #endregion
+
+        #region 执行无返回值的sql语句
+        /// <summary>
+        /// 执行无返回值的sql语句
+        /// </summary>
+        /// <param name="commandString"></param>
+        /// <returns></returns>
+        public bool ExecuteNonQuery(string commandString)
+        {
+            //打开连接失败,不执行查询
+            if (!OpenConnection())
+                return false;
+            try
+            {
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.CommandText = commandString;
+                cmdObj.ExecuteNonQuery();
+            }
+            catch (Exception ex)
+            {
+                CloseConnection();
+                _message = ex.Message;
+                Log.Debug(ex);
+                Log.Debug("ex:" + commandString);
+                return false;
+            }
+            CloseConnection();
+            return true;
+        }
+        #endregion
+
+        #region 执行返回值的sql
+        /// <summary>
+        /// 执行返回值的sql
+        /// </summary>
+        /// <param name="commandString"></param>
+        /// <returns></returns>
+        public object ExecuteResult(string commandString)
+        {
+            object reobj = null;
+
+            //打开连接失败,不执行查询
+            if (!OpenConnection()) return reobj;
+
+            try
+            {
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.CommandText = commandString;
+                reobj = cmdObj.ExecuteScalar();
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+            }
+            finally
+            {
+                CloseConnection();
+            }
+            return reobj;
+        }
+        #endregion
+
+        #region 执行sql命令组
+        /// <summary>
+        /// 执行sql命令组
+        /// </summary>
+        /// <param name="arrSql"></param>
+        /// <returns></returns>
+        public bool ExecuteSqls(ArrayList arrSql)
+        {
+            if (!OpenConnection()) return false;
+
+            try
+            {
+                OracleCommand cmdObj = CreateCommand();
+                foreach (var sql in arrSql)
+                {
+                    cmdObj.CommandText = sql.ToString();
+                    cmdObj.ExecuteNonQuery();
+                }
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                return false;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+            return true;
+        }
+        #endregion
+
+        #region 事务控制执行sql命令组
+        /// <summary>
+        /// 事务控制执行sql命令组
+        /// </summary>
+        /// <param name="arrSql"></param>
+        /// <returns></returns>
+        public bool ExecuteSqlByAffair(ArrayList arrSql)
+        {
+            if (!OpenConnection()) return false;
+            OracleTransaction transObj = _con_SQL.BeginTransaction();//开始事务操作
+            try
+            {
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.Transaction = transObj;//指定command的事务对象
+                foreach (var sql in arrSql)
+                {
+                    cmdObj.CommandText = sql.ToString();
+                    cmdObj.ExecuteNonQuery();
+                }
+                transObj.Commit();
+            }
+            catch (Exception ex)
+            {
+                transObj.Rollback();
+                _message = ex.Message;
+                Log.Debug(ex);
+                foreach (var sql in arrSql)
+                {
+                    Log.Debug("ex:" + sql);
+                }
+                return false;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 事务控制执行sql命令组
+        /// </summary>
+        /// <param name="dicSql"></param>
+        /// <returns></returns>
+        public bool ExecuteSqlsByAffair(Dictionary<string, string> dicSql)
+        {
+            if (!OpenConnection())
+                return false;
+            OracleTransaction transObj = _con_SQL.BeginTransaction();
+            string sqlPath = string.Empty;
+            try
+            {
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.Transaction = transObj;
+                foreach (var item in dicSql)
+                {
+                    sqlPath = item.Key;
+                    string[] commands = System.Text.RegularExpressions.Regex.Split(item.Value + " ",
+                        "[ |\r\n]go[ |\r\n]", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+                    foreach (string sql in commands)
+                        if (sql.Trim().Length > 0)
+                        {
+                            cmdObj.CommandText = sql;
+                            cmdObj.ExecuteNonQuery();
+                        }
+                }
+                transObj.Commit();
+            }
+            catch (Exception ex)
+            {
+                transObj.Rollback();
+                _message = string.Format("执行 {0} 出错;\r\n", sqlPath);
+                _message += ex.Message;
+                Log.Debug(_message);
+                return false;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 事务控制执行sql命令组
+        /// </summary>
+        /// <param name="dicSql">sql命令组</param>
+        /// <param name="dicRecord">返回的日志</param>
+        /// <returns></returns>
+        public bool ExecuteSqlsByAffair(Dictionary<string, string> dicSql, ref Dictionary<string, string> dicRecord)
+        {
+            if (!OpenConnection()) return false;
+            OracleTransaction transObj = _con_SQL.BeginTransaction();
+            string sqlPath = string.Empty;
+            try
+            {
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.Transaction = transObj;
+                foreach (var item in dicSql)
+                {
+                    sqlPath = item.Key;
+                    string[] commands = System.Text.RegularExpressions.Regex.Split(item.Value + " ",
+                        "[ |\r\n]go[ |\r\n]", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
+                    foreach (string sql in commands)
+                        if (sql.Trim().Length > 0)
+                        {
+                            cmdObj.CommandText = sql;
+                            cmdObj.ExecuteNonQuery();
+                        }
+
+                    if (dicRecord != null)
+                        dicRecord.Add(sqlPath, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", System.Globalization.DateTimeFormatInfo.InvariantInfo));
+                }
+                transObj.Commit();
+            }
+            catch (Exception ex)
+            {
+                _message = string.Format("执行{0}出错:\r\n", sqlPath);
+                _message += ex.Message;
+                Log.Debug(_message);
+                try { transObj.Rollback(); }
+                catch { }
+                return false;
+            }
+            return true;
+        }
+        #endregion
+
+        #region 获取数据表
+        /// <summary>
+        /// 获取数据表
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <returns></returns>
+        public DataTable GetDataTable(string sql)
+        {
+            Log.Debug(sql);
+            if (!OpenConnection()) return null;
+            try
+            {
+                DataTable dt = new DataTable();
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.CommandText = sql;
+                OracleDataAdapter daObj = new OracleDataAdapter(cmdObj);
+                daObj.Fill(dt);
+                return dt;
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                Log.Debug("ex:" + sql);
+                return null;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+        }
+
+        /// <summary>
+        /// 获取数据表
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <param name="tableName"></param>
+        /// <returns></returns>
+        public DataTable GetDataTable(string sql, string tableName)
+        {
+            if (!OpenConnection()) return null;
+            try
+            {
+                DataTable dt = new DataTable();
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.CommandText = sql;
+                OracleDataAdapter daObj = new OracleDataAdapter(cmdObj);
+                daObj.Fill(dt);
+                dt.TableName = tableName;
+                return dt;
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                return null;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+        }
+
+        public DataTable GetDataTable(string sql, string tableName, int currentPage, int pageSize)
+        {
+            if (!OpenConnection()) return null;
+            try
+            {
+                DataSet ds = new DataSet();
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.CommandText = sql;
+                OracleDataAdapter daObj = new OracleDataAdapter(cmdObj);
+                daObj.Fill(ds, (currentPage - 1) * pageSize, pageSize, tableName);
+                return ds.Tables[0];
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                return null;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+        }
+        #endregion
+
+        #region 获取数据集
+        /// <summary>
+        /// 获取数据集
+        /// </summary>
+        /// <param name="sql"></param>
+        /// <returns></returns>
+        public DataSet GetDataSet(string sql)
+        {
+            if (!OpenConnection()) return null;
+            try
+            {
+                DataSet ds = new DataSet();
+                OracleCommand cmdObj = CreateCommand();
+                cmdObj.CommandText = sql;
+                OracleDataAdapter daObj = new OracleDataAdapter(cmdObj);
+                daObj.Fill(ds);
+                return ds;
+            }
+            catch (Exception ex)
+            {
+                _message = ex.Message;
+                Log.Debug(ex);
+                return null;
+            }
+            finally
+            {
+                CloseConnection();
+            }
+        }
+        #endregion
+    }
+}

+ 32 - 0
XmlDocumentAnalysis/Program.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.ServiceProcess;
+using System.Text;
+using System.Threading.Tasks;
+using static System.Net.Mime.MediaTypeNames;
+
+using System.Windows.Forms;
+
+namespace XmlDucumentAnalysis
+{
+    static class Program
+    {
+        /// <summary>
+        /// 应用程序的主入口点。
+        /// </summary>
+        static void Main()
+        {
+            ServiceBase[] ServicesToRun;
+            ServicesToRun = new ServiceBase[]
+            {
+                new XmlDocumentAnalysis()
+            };
+            ServiceBase.Run(ServicesToRun);
+
+            System.Windows.Forms.Application.EnableVisualStyles();
+            System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
+            System.Windows.Forms.Application.Run(new Form1());
+        }
+    }
+}

+ 57 - 0
XmlDocumentAnalysis/ProjectInstaller.Designer.cs

@@ -0,0 +1,57 @@
+namespace XmlDucumentAnalysis
+{
+    partial class ProjectInstaller
+    {
+        /// <summary>
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 组件设计器生成的代码
+
+        /// <summary>
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
+            this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
+            // 
+            // serviceProcessInstaller1
+            // 
+            this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
+            this.serviceProcessInstaller1.Password = null;
+            this.serviceProcessInstaller1.Username = null;
+            // 
+            // serviceInstaller1
+            // 
+            this.serviceInstaller1.ServiceName = "xmlAnalysisService";
+            // 
+            // ProjectInstaller
+            // 
+            this.Installers.AddRange(new System.Configuration.Install.Installer[] {
+            this.serviceProcessInstaller1,
+            this.serviceInstaller1});
+
+        }
+
+        #endregion
+
+        private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
+        private System.ServiceProcess.ServiceInstaller serviceInstaller1;
+    }
+}

+ 19 - 0
XmlDocumentAnalysis/ProjectInstaller.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Configuration.Install;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace XmlDucumentAnalysis
+{
+    [RunInstaller(true)]
+    public partial class ProjectInstaller : System.Configuration.Install.Installer
+    {
+        public ProjectInstaller()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 129 - 0
XmlDocumentAnalysis/ProjectInstaller.resx

@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="serviceProcessInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>20, 26</value>
+  </metadata>
+  <metadata name="serviceInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>246, 22</value>
+  </metadata>
+  <metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+</root>

+ 36 - 0
XmlDocumentAnalysis/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("XmlDucumentAnalysis")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("XmlDucumentAnalysis")]
+[assembly: AssemblyCopyright("Copyright ©  2023")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 会使此程序集中的类型
+//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("bc61ed6a-af0c-4db9-8553-1f76f96ac0e6")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
+// 方法是按如下所示使用“*”: :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 430 - 0
XmlDocumentAnalysis/SQLHelper.cs

@@ -0,0 +1,430 @@
+
+using System;
+using System.Collections;
+using System.Data;
+using System.Data.SqlClient;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace DataPumpWindowsService
+{
+	public class SQLHelper
+	{
+        private const int outTime = 360;
+		private string m_sMessage = "";
+		public SqlConnection m_conMS_SQL;
+		public string Message
+		{
+			get
+			{
+				return this.m_sMessage;
+			}
+		}
+
+        public SQLHelper(string connectstring)
+        {
+            this.m_conMS_SQL = new SqlConnection(connectstring);
+        }
+
+		public bool OpenConnection()
+		{
+			bool result;
+			if (this.m_conMS_SQL.State == ConnectionState.Open)
+			{
+				result = true;
+			}
+			else
+			{
+				try
+				{
+					this.m_conMS_SQL.Open();
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = false;
+					return result;
+				}
+				if (this.m_conMS_SQL.State != ConnectionState.Open)
+				{
+					this.m_sMessage = "打开连接失败";
+					result = false;
+				}
+				else
+				{
+					result = true;
+				}
+			}
+			return result;
+		}
+		public bool CloseConnection()
+		{
+			bool result;
+			if (this.m_conMS_SQL.State == ConnectionState.Closed)
+			{
+				result = true;
+			}
+			else
+			{
+				try
+				{
+					this.m_conMS_SQL.Close();
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = false;
+					return result;
+				}
+				if (this.m_conMS_SQL.State != ConnectionState.Closed)
+				{
+					this.m_sMessage = "关闭连接失败";
+					result = false;
+				}
+				else
+				{
+					result = true;
+				}
+			}
+			return result;
+		}
+		public bool ExecuteNonQuery(string p_sCommand)
+		{
+			bool result;
+			if (!this.OpenConnection())
+			{
+				result = false;
+			}
+			else
+			{
+				try
+				{
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					sqlCommand.ExecuteNonQuery();
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					this.CloseConnection();
+					result = false;
+					return result;
+				}
+				this.CloseConnection();
+				result = true;
+			}
+			return result;
+		}
+		public object ExecuteResult(string p_sCommand)
+		{
+			object obj = null;
+			object result;
+			if (!this.OpenConnection())
+			{
+				result = obj;
+			}
+			else
+			{
+				try
+				{
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					obj = sqlCommand.ExecuteScalar();
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+				result = obj;
+			}
+			return result;
+		}
+		public DataTable ExecuteResultTable(string p_sCommand)
+		{
+			DataTable dataTable = null;
+			DataTable result;
+			if (!this.OpenConnection())
+			{
+				result = dataTable;
+			}
+			else
+			{
+				try
+				{
+					dataTable = new DataTable();
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					sqlCommand.ExecuteNonQuery();
+					new SqlDataAdapter
+					{
+						SelectCommand = sqlCommand
+					}.Fill(dataTable);
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+				result = dataTable;
+			}
+			return result;
+		}
+		public bool ExecuteSqls(ArrayList p_oSqls)
+		{
+			bool result;
+			if (!this.OpenConnection())
+			{
+				result = false;
+			}
+			else
+			{
+				try
+				{
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					for (int i = 0; i < p_oSqls.Count; i++)
+					{
+						sqlCommand.CommandText = p_oSqls[i].ToString();
+						sqlCommand.ExecuteNonQuery();
+					}
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = false;
+					return result;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+				result = true;
+			}
+			return result;
+		}
+		public bool ExecuteSqlsByAffair(ArrayList p_oSqls)
+		{
+			bool result;
+			if (!this.OpenConnection())
+			{
+				result = false;
+			}
+			else
+			{
+				SqlTransaction sqlTransaction = this.m_conMS_SQL.BeginTransaction();
+				try
+				{
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.Transaction = sqlTransaction;
+					for (int i = 0; i < p_oSqls.Count; i++)
+					{
+						sqlCommand.CommandText = p_oSqls[i].ToString();
+						sqlCommand.ExecuteNonQuery();
+					}
+					sqlTransaction.Commit();
+				}
+				catch (Exception ex)
+				{
+					sqlTransaction.Rollback();
+					this.m_sMessage = ex.Message;
+					result = false;
+					return result;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+				result = true;
+			}
+			return result;
+		}
+		public DataTable GetDataTable(string p_sCommand)
+		{
+			DataTable result;
+			if (!this.OpenConnection())
+			{
+				result = null;
+			}
+			else
+			{
+				try
+				{
+					DataTable dataTable = new DataTable();
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+					sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
+					sqlDataAdapter.Fill(dataTable);
+					result = dataTable;
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = null;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+			}
+			return result;
+		}
+		public DataTable GetDataTable(string p_sCommand, string p_sTableName)
+		{
+			DataTable result;
+			if (!this.OpenConnection())
+			{
+				result = null;
+			}
+			else
+			{
+				try
+				{
+					DataTable dataTable = new DataTable();
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
+					sqlDataAdapter.Fill(dataTable);
+					dataTable.TableName = p_sTableName;
+					result = dataTable;
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = null;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+			}
+			return result;
+		}
+		public DataTable GetDataTable(string p_sCommand, string p_sTableName, int p_iCurrentPage, int p_iPageSize)
+		{
+			DataTable result;
+			if (!this.OpenConnection())
+			{
+				result = null;
+			}
+			else
+			{
+				try
+				{
+					DataSet dataSet = new DataSet();
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
+					sqlDataAdapter.Fill(dataSet, (p_iCurrentPage - 1) * p_iPageSize, p_iPageSize, p_sTableName);
+					result = dataSet.Tables[0];
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = null;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+			}
+			return result;
+		}
+		public DataSet GetDataSet(string p_sCommand)
+		{
+			DataSet result;
+			if (!this.OpenConnection())
+			{
+				result = null;
+			}
+			else
+			{
+				try
+				{
+					DataSet dataSet = new DataSet();
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					sqlCommand.CommandText = p_sCommand;
+					SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
+					sqlDataAdapter.Fill(dataSet);
+					result = dataSet;
+				}
+				catch (Exception ex)
+				{
+					this.m_sMessage = ex.Message;
+					result = null;
+				}
+				finally
+				{
+					this.CloseConnection();
+				}
+			}
+			return result;
+		}
+		public bool RunSqlScript(string s_Command)
+		{
+			bool result;
+			if (!this.OpenConnection())
+			{
+				result = false;
+			}
+			else
+			{
+				if (s_Command == string.Empty)
+				{
+					result = false;
+				}
+				else
+				{
+					string[] array = Regex.Split(s_Command + " ", "[ |\r\n]go[ |\r\n]", RegexOptions.IgnoreCase);
+					SqlCommand sqlCommand = this.m_conMS_SQL.CreateCommand();
+                    sqlCommand.CommandTimeout = 360;
+					SqlTransaction sqlTransaction = this.m_conMS_SQL.BeginTransaction();
+					sqlCommand.Connection = this.m_conMS_SQL;
+					sqlCommand.Transaction = sqlTransaction;
+					try
+					{
+						string[] array2 = array;
+						for (int i = 0; i < array2.Length; i++)
+						{
+							string text = array2[i];
+							if (text.Trim().Length > 0)
+							{
+								sqlCommand.CommandText = text;
+								sqlCommand.ExecuteNonQuery();
+							}
+						}
+						sqlTransaction.Commit();
+					}
+					catch (Exception ex)
+					{
+						this.m_sMessage = ex.Message;
+						sqlTransaction.Rollback();
+						result = false;
+						return result;
+					}
+					finally
+					{
+						sqlTransaction.Dispose();
+						this.CloseConnection();
+					}
+					result = true;
+				}
+			}
+			return result;
+		}
+	}
+}

+ 40 - 0
XmlDocumentAnalysis/XmlDocumentAnalysis.Designer.cs

@@ -0,0 +1,40 @@
+namespace XmlDucumentAnalysis
+{
+    partial class XmlDocumentAnalysis
+    {
+        /// <summary> 
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region 组件设计器生成的代码
+
+        /// <summary> 
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            // 
+            // XmlDocumentAnalysis
+            // 
+            this.ServiceName = "Service1";
+
+        }
+
+        #endregion
+    }
+}

+ 753 - 0
XmlDocumentAnalysis/XmlDocumentAnalysis.cs

@@ -0,0 +1,753 @@
+using System.ServiceProcess;
+using System.Configuration;
+using System.Collections.Generic;
+using System.IO;
+using System.Security.Cryptography;
+using System;
+using System.Timers;
+using System.Xml;
+using DataPumpWindowsService;
+using System.Data;
+using XmlDucumentAnalysis.model;
+using ICSharpCode.SharpZipLib.Tar;
+using System.Text;
+
+namespace XmlDucumentAnalysis
+{
+    public partial class XmlDocumentAnalysis : ServiceBase
+    {
+        private Timer timer = new Timer();
+        private string baseFilePath
+        {
+            get;
+            set;
+        }
+        private string csvBaseFilePath
+        {
+            get;
+            set;
+        }
+        private string xmlBasePath
+        {
+            get;
+            set;
+        }
+        private string copyXmlFilePath
+        {
+            get;
+            set;
+        }
+        private string ConnectString
+        {
+            get;
+            set;
+        }
+        private DateTime minDateTime
+        {
+            get;
+            set;
+        }
+        private DateTime maxDateTime
+        {
+            get;
+            set;
+        }
+        public XmlDocumentAnalysis()
+        {
+            InitializeComponent();
+            // 定时任务时间间隔为12小时
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["interval"]))
+            {
+                this.timer.Interval = (double)int.Parse(ConfigurationManager.AppSettings["interval"]);
+            }
+            // xml底层目录
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["xmlBasePath"]))
+            {
+                this.xmlBasePath = ConfigurationManager.AppSettings["xmlBasePath"];
+            }
+            // 复制xml底层目录
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["copyXmlFilePath"]))
+            {
+                this.copyXmlFilePath = ConfigurationManager.AppSettings["copyXmlFilePath"];
+            }
+            // 获取配置里的Oracle连接信息
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["default"]))
+            {
+                this.ConnectString = ConfigurationManager.AppSettings["default"];
+            }
+            // 获取配置里的Oracle连接信息
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["baseFilePath"]))
+            {
+                this.baseFilePath = ConfigurationManager.AppSettings["baseFilePath"];
+            }
+            // 获取csv存放路径
+            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["csvBaseFilePath"]))
+            {
+                this.csvBaseFilePath = ConfigurationManager.AppSettings["csvBaseFilePath"];
+            }
+        }
+        protected override void OnStart(string[] args)
+        {
+            Log.Debug("Start.");
+            this.timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
+            this.timer.Enabled = true;
+            this.timer.Start();
+        }
+
+        protected override void OnStop()
+        {
+            this.timer.Stop();
+            Log.Debug("Stop.");
+        }
+
+        // xml解析方法并设置XmlModel属性
+        public static XmlModel XmlFileAnalysis(string filePath, XmlModel xmlModel)
+        {
+            Log.Info("开始分析" + filePath);
+            //这一步实例化一个xml命名空间管理器
+            XmlDocument doc = new XmlDocument();
+            doc.Load(filePath);
+            XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
+            nsMgr.AddNamespace("x", "http://www.verint.com/xmlns/recording20080320");
+
+            // 获取节点内容
+            XmlNode contacts = doc.SelectSingleNode("x:recording/x:contacts", nsMgr);
+            XmlNode contact = contacts.FirstChild;
+            if (contact != null)
+            {
+                XmlNode sessions = contact.SelectSingleNode("x:sessions", nsMgr);
+                XmlNode session = sessions.FirstChild;
+                XmlNode aniNode = session.SelectSingleNode("x:ani", nsMgr);
+                if (aniNode==null)
+                {
+                    return xmlModel;
+                }
+                // 主叫号码
+                string ani = aniNode.InnerText;
+                // 被叫号码
+                string dnis = session.SelectSingleNode("x:dnis", nsMgr).InnerText;
+                // 通话时长
+                string duration = session.SelectSingleNode("x:duration", nsMgr).InnerText;
+                // 录音流水ID
+                string parentinum = session.Attributes["x:parentinum"].Value;
+                // 通话拨打时间
+                string starttime = session.SelectSingleNode("x:starttime", nsMgr).InnerText;
+                starttime = SplitDateTimeString(starttime);
+                // 呼叫类型
+                string direction = session.SelectSingleNode("x:direction", nsMgr).InnerText;
+                // 录音流水ID
+                string switch_call_id = session.SelectSingleNode("x:switch_call_id", nsMgr).InnerText;
+
+                if ("Inbound".Equals(direction))
+                {
+                    direction = "0";
+                }
+                else
+                {
+                    direction = "1";
+                }
+                // 平台code
+                string switch_id = session.SelectSingleNode("x:switch_id", nsMgr).InnerText;
+                // 坐席ID
+                XmlNode sessionTags = session.SelectSingleNode("x:tags", nsMgr);
+                XmlNode sessionTag = sessionTags.FirstChild;
+                string agentid = "";
+                foreach (XmlNode xn1 in sessionTag)
+                {
+                    XmlElement xe1 = (XmlElement)xn1;
+                    if (xe1.GetAttribute("x:key").ToString() == "agentid")
+                    {
+                        agentid = xn1.InnerText;
+                        break;
+                    }
+                }
+                xmlModel.callerNumber = ani;
+                xmlModel.destinationNumber = dnis;
+                xmlModel.duration = duration;
+                xmlModel.dateStartCall = starttime;
+                xmlModel.callType = direction;
+                xmlModel.platformCode = switch_id;
+                xmlModel.agentId = agentid;
+                xmlModel.switch_call_id = switch_call_id;
+            }
+            // 通话结束时间
+            XmlNode tags = doc.SelectSingleNode("x:recording/x:segment/x:tags", nsMgr);
+            XmlNodeList tagList = tags.ChildNodes;
+            foreach (XmlNode xn in tagList)
+            {
+                XmlNode xn2 = xn.FirstChild;
+                string childAttributesValue = xn2.Attributes["x:key"].Value;
+                if ("endtime".Equals(childAttributesValue))
+                {
+                    string endtime = xn2.InnerText;
+                    endtime = SplitDateTimeString(endtime);
+                    xmlModel.dateHangup = endtime;
+                    break;
+                }
+            }
+            return xmlModel;
+        }
+        // 截取时间段
+        public static string SplitDateTimeString(string dateTimeString)
+        {
+            dateTimeString = dateTimeString.Substring(0, 19);
+            dateTimeString = dateTimeString.Replace("T", " ");
+            return dateTimeString;
+        }
+        // 获取文件MD5值方法
+        public static string getMD5ByMD5CryptoService(string path)
+        {
+            if (!File.Exists(path)) return "";
+            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
+            MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
+            byte[] buffer = md5Provider.ComputeHash(fs);
+            string resule = BitConverter.ToString(buffer);
+            md5Provider.Clear();
+            fs.Close();
+            return resule;
+        }
+        // 生成csv文件公共方法
+        private void CreateCsvFile(string filePath, List<string> lineList)
+        {
+            System.IO.FileInfo fi = new System.IO.FileInfo(filePath);
+            if (!fi.Directory.Exists)
+            {
+                fi.Directory.Create();  //文件不存在,创建文件
+            }
+
+            System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Create, System.IO.FileAccess.Write);
+            System.IO.StreamWriter sw = new System.IO.StreamWriter(fs, Encoding.Default);
+            // 循环列数组  写入表数据
+            foreach (string line in lineList)
+            {
+                sw.WriteLine(line);
+            }
+            sw.Close();
+            fs.Close();
+        }
+        // 生成csv文件定时任务
+        private void CreateCsvFileJob(DateTime minTime, DateTime maxTime)
+        {
+            Log.Debug("开始生成csv文件任务");
+            // 定义表数组    
+            List<string> lineList = new List<string>();
+            // 定义表头
+            lineList.Add("录音流水ID,录音文件名,数据包,通话时长(单位:秒),通话拨打时间,通话挂机时间,主叫号码,被叫号码,坐席工号,坐席ID,质检场景,呼叫类型(0:呼入,1:呼出),客户号,平台code,扩展字段1,扩展字段2,扩展字段3,扩展字段4,扩展字段5,扩展字段6");
+            OracleHelper oracleHelper = null;
+            DataTable dataList = new DataTable();
+            try
+            {
+                oracleHelper = new OracleHelper(this.ConnectString);
+                dataList = getSqlField(oracleHelper, minTime, maxTime);
+                oracleHelper = null;
+            }
+            catch (Exception exp)
+            {
+                Log.Debug(exp);
+            }
+            finally
+            {
+                bool flag = oracleHelper != null;
+                if (flag)
+                {
+                    oracleHelper.CloseConnection();
+                    oracleHelper = null;
+                }
+            }
+            // 获取录音流水文件List
+            string lastTimeFileName = this.baseFilePath + "\\lastTimeFileName.txt";
+            Log.Debug("获取上次分析路径为:" + lastTimeFileName);
+            List<string> filePathList = new List<string>();
+            // 判断文件是否存在
+            // 判断文件是否存在
+            if (File.Exists(lastTimeFileName))
+            {
+
+                string catalog = File.ReadAllText(lastTimeFileName);
+                Log.Debug("成功获取上次记录:" + catalog);
+                // 上一次copy文件夹的目录级别
+                string[] catalogList = catalog.Split('\\');
+                int catalogListSize = catalogList.Length;
+                string level1Catalog = catalogList[catalogListSize - 3];
+                string level2Catalog = catalogList[catalogListSize - 2];
+                string level3Catalog = catalogList[catalogListSize - 1];
+                for (int i = int.Parse(level1Catalog); i <= 99; i++)
+                {
+
+                    string level1Dir = this.copyXmlFilePath + "\\" + i.ToString().PadLeft(3, '0');
+                    Log.Debug("判断文件夹路径是否存在" + level1Dir);
+                    // 判断文件夹路径是否存在 不存在则结束循环
+                    if (!Directory.Exists(level1Dir))
+                    {
+                        break;
+                    }
+                    for (int j = i == int.Parse(level1Catalog) ? int.Parse(level2Catalog) : 0; j <= 99; j++)
+                    {
+                        string level2Dir = level1Dir + "\\" + j.ToString().PadLeft(2, '0');
+                        Log.Debug("判断文件夹路径是否存在" + level2Dir);
+                        // 判断文件夹路径是否存在 不存在则结束循环
+                        if (!Directory.Exists(level2Dir))
+                        {
+                            break;
+                        }
+                        for (int k = j == int.Parse(level2Catalog) ? int.Parse(level3Catalog) : 0; k <= 99; k++)
+                        {
+
+                            string level3Dir = level2Dir + "\\" + k.ToString().PadLeft(2, '0');
+                            Log.Debug("判断文件夹路径是否存在" + level3Dir);
+                            // 判断文件夹路径是否存在 不存在则结束循环
+                            if (!Directory.Exists(level3Dir))
+                            {
+                                break;
+                            }
+                            filePathList = GetDirectories(level3Dir, filePathList);
+                            string filePathString = string.Join(",", filePathList);
+                            Log.Debug("扫描到的文件列表为:" + filePathString);
+                        }
+                    }
+                }
+            }
+            // 获取当前日期格式
+            string nowDate = maxTime.AddHours(-1).ToString("yyyy-MM-dd");
+            string newFilePath = this.csvBaseFilePath + "\\" + nowDate;
+
+            // 最后一个文件名
+            string lastFileName = "";
+
+            if (dataList != null && dataList.Rows.Count > 0)
+            {
+                foreach (string path in filePathList)
+                {
+                    // 获取录音文件信息
+                    FileInfo xmlFile = new FileInfo(path);
+                    string extension = Path.GetExtension(path);
+                    if (".xml".Equals(extension))
+                    {
+                        // 设置xmlModel属性
+                        XmlModel xmlModel = new XmlModel();
+                        XmlFileAnalysis(path, xmlModel);
+                        string switchCallId = xmlModel.switch_call_id;
+                        if (switchCallId !=null )
+                        {
+                            DataRow[] row = dataList.Select("callid = " + switchCallId);
+                            if (row.Length > 0)
+                            {
+                                //拷贝到csv当天目录下
+                                string wavPath = path.Replace("xml", "wav");
+                                CopyToFile(wavPath, newFilePath);
+                                DataRow dr = row[0];
+                                // 获取录音ID   
+                                string recordingId = dr[0].ToString();
+                                // 获取质检场景
+                                string caltype = dr[1].ToString();
+                                caltype = caltype.Replace("-", "_");
+                                int index = caltype.IndexOf("(");
+                                if (index >= 0)
+                                {
+                                    caltype = caltype.Substring(0, index);
+                                }
+                                // 获取入司时间
+                                string employedDate = dr[2].ToString();
+                                // 获取组别
+                                string title = dr[3].ToString();
+                                // 客户评价
+                                string evaluation = dr[4].ToString();
+                                // 客户等级
+                                string level = dr[5].ToString();
+                                // 客户类别
+                                string category = dr[6].ToString();
+                                // 坐席工号
+                                string staffname = dr[7].ToString();
+                                // 坐席ID
+                                string agent_id = dr[8].ToString();
+                                // 业务号
+                                string remark6 = dr[9].ToString();
+
+                                xmlModel.recordingId = recordingId;
+                                xmlModel.recordingFileName = Path.GetFileNameWithoutExtension(path) + ".wav";
+                                xmlModel.sceneName = caltype;
+                                xmlModel.remark1 = employedDate;
+                                xmlModel.remark2 = title;
+                                xmlModel.remark3 = evaluation;
+                                xmlModel.remark4 = level;
+                                xmlModel.remark5 = category;
+                                xmlModel.agentCti = staffname;
+                                xmlModel.agentId = agent_id;
+                                xmlModel.remark6 = remark6;
+
+                                lastFileName = Path.GetFileNameWithoutExtension(path) + ".wav";
+
+                                // 定义列字符串
+                                string lineString = "";
+                                // 遍历对象属性赋值拼接字符串
+                                foreach (System.Reflection.PropertyInfo p in xmlModel.GetType().GetProperties())
+                                {
+                                    lineString += p.GetValue(xmlModel);
+                                    lineString += ",";
+                                }
+                                lineString = lineString.Remove(lineString.LastIndexOf(","));
+                                lineString = lineString.Remove(lineString.LastIndexOf(","));
+                                lineList.Add(lineString);
+                            }
+                        }
+                    }
+                }
+            }
+            string filePath = newFilePath + "\\" + maxTime.ToString("yyyy-MM-ddHH") + ".csv";  //文件路径
+            CreateCsvFile(filePath, lineList);
+            // 获取最后一个文件目录完成csv生成之后将最后一个文件所在目录缓存进文件
+            if (!string.IsNullOrEmpty(lastFileName))
+            {
+                string directory1 = lastFileName.Substring(6, 3);
+                string directory2 = lastFileName.Substring(9, 2);
+                string directory3 = lastFileName.Substring(11, 2);
+                string lastFilePath = this.copyXmlFilePath + "\\" + directory1 + "\\" + directory2 + "\\" + directory3;
+                string path = this.baseFilePath + "\\lastTimeFileName.txt";
+                if (File.Exists(path))
+                {
+                    File.Delete(path);
+                }
+                File.AppendAllText(path, lastFilePath);
+            }
+        }
+        // 拷贝文件到另一个文件夹下
+        // <param name="sourceName">源文件路径</param>
+        // <param name="folderPath">目标路径(目标文件夹)</param>
+        private void CopyToFile(string sourceName, string folderPath)
+        {
+            if (!Directory.Exists(folderPath))
+            {
+                Directory.CreateDirectory(folderPath);
+            }
+            //当前文件如果不用新的文件名,那么就用原文件文件名
+            string fileName = Path.GetFileName(sourceName);
+            //这里可以给文件换个新名字,如下:
+            //string fileName = string.Format("{0}.{1}", "newFileText", "txt");
+
+            //目标整体路径
+            string targetPath = Path.Combine(folderPath, fileName);
+
+            //Copy到新文件下
+            FileInfo file = new FileInfo(sourceName);
+            if (file.Exists)
+            {
+                //true 为覆盖已存在的同名文件,false 为不覆盖
+                file.CopyTo(targetPath, true);
+            }
+        }
+
+        private void CopyToFile(string sourceName, string folderPath, string newFileName)
+        {
+            if (!Directory.Exists(folderPath))
+            {
+                Directory.CreateDirectory(folderPath);
+            }
+            //这里可以给文件换个新名字,如下:
+            //目标整体路径
+            string targetPath = Path.Combine(folderPath, newFileName);
+
+            //Copy到新文件下
+            FileInfo file = new FileInfo(sourceName);
+            if (file.Exists)
+            {
+                //true 为覆盖已存在的同名文件,false 为不覆盖
+                file.CopyTo(targetPath, true);
+            }
+        }
+        // 时间检测 定时任务
+        public void OnTimer(object sender, ElapsedEventArgs args)
+        {
+            // 时间等于12:30  执行中午的录音拷贝
+            if (DateTime.Now.Hour == 12 && DateTime.Now.Minute == 30)
+            {
+                // 当天0时0分0秒:
+                minDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                // 当天12:00
+                maxDateTime = minDateTime.AddHours(12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "录音文件拷贝任务");
+                // 调用录音拷贝任务
+                RecordingCopyJob(minDateTime, maxDateTime);
+            }
+            // 时间等于13: 00  执行中午的生成csv文件
+            else if (DateTime.Now.Hour == 13 && DateTime.Now.Minute == 00)
+            {
+                // 当天0时0分0秒:
+                minDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                // 当天12:00
+                maxDateTime = minDateTime.AddHours(12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "的生成csv文件任务");
+                CreateCsvFileJob(minDateTime, maxDateTime);
+            }
+            // 时间等于00:30 执行下午的录音拷贝
+            else if (DateTime.Now.Hour == 00 && DateTime.Now.Minute == 30)
+            {
+
+                maxDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                minDateTime = maxDateTime.AddHours(-12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "录音文件拷贝任务");
+                RecordingCopyJob(minDateTime, maxDateTime);
+            }
+            // 时间等于1:00 执行下午的生成csv文件
+            else if (DateTime.Now.Hour == 1 && DateTime.Now.Minute == 00)
+            {
+                maxDateTime = Convert.ToDateTime(DateTime.Now.ToString("D").ToString());
+                minDateTime = maxDateTime.AddHours(-12);
+                Log.Debug("开始执行" + minDateTime + "至" + maxDateTime + "的生成csv文件任务");
+                CreateCsvFileJob(minDateTime, maxDateTime);
+            }
+            else if (DateTime.Now.Hour == 2 && DateTime.Now.Minute == 00)
+            {
+                Log.Debug("开始执行"+ DateTime.Now.Hour + "清理过期录音文件任务");
+                CleanCsvRecardFile(this.copyXmlFilePath, 8);
+                CleanCsvRecardFile(this.csvBaseFilePath, 8);
+            }
+        }
+
+        // 录音拷贝任务
+        public void RecordingCopyJob(DateTime minTime, DateTime maxTime)
+        {
+            Log.Debug("开始录音拷贝处理");
+            // 定义文件路径列表
+            List<string> list = new List<string>();
+            // 获取某文件夹里最新的文件夹
+            string path = this.baseFilePath + "\\lastTimeFileName.txt";
+            Log.Debug("获取上次拷贝地址为:" + path);
+            // 判断文件是否存在
+            if (File.Exists(path))
+            {
+                Log.Debug("成功获取上次记录:" + path);
+                string catalog = File.ReadAllText(path);
+                // 上一次copy文件夹的目录级别
+                string[] catalogList = catalog.Split('\\');
+                int catalogListSize = catalogList.Length;
+                string level1Catalog = catalogList[catalogListSize - 3];
+                string level2Catalog = catalogList[catalogListSize - 2];
+                string level3Catalog = catalogList[catalogListSize - 1];
+                if (level3Catalog == "00")
+                {
+                    level3Catalog = "99";
+                    if (level2Catalog == "00")
+                    {
+                        level2Catalog = "99";
+                        level1Catalog = (int.Parse(level1Catalog) - 1).ToString().PadLeft(3, '0');
+                    }
+                    else
+                    {
+                        level2Catalog = (int.Parse(level2Catalog) - 1).ToString().PadLeft(2, '0');
+                    }
+                }
+                else
+                {
+                    level3Catalog = (int.Parse(level3Catalog) - 1).ToString().PadLeft(2, '0');
+                }
+
+                // 获取文件夹内的最新文件夹(max:一级目录,max2:二级目录,max3:三级目录)
+                FtpHelper ftpHelper = new FtpHelper();
+                List<string> dirctoryList = ftpHelper.GetDirctory(this.xmlBasePath);
+                int max = getMaxNumber(dirctoryList);
+                int max2 = 0;
+                int max3 = 0;
+                // 循环获取对象中的文件路径
+                for (int i = int.Parse(level1Catalog); i <= max; i++)
+                {
+                    string path2 = this.xmlBasePath + i.ToString().PadLeft(3, '0') + "/";
+                    string copyPath2 = this.copyXmlFilePath + "\\" + i.ToString().PadLeft(3, '0');
+                    string path3 = "";
+                    string copyPath3 = "";
+                    string path4 = "";
+                    string copyPath4 = "";
+                    List<string> dirctoryList2 = ftpHelper.GetDirctory(path2);
+                    max2 = getMaxNumber(dirctoryList2);
+                    if (i > int.Parse(level1Catalog))
+                    {
+                        level2Catalog = "0";
+                        level3Catalog = "0";
+                    }
+                    for (int j = int.Parse(level2Catalog); j <= max2; j++)
+                    {
+                        path3 = path2 + j.ToString().PadLeft(2, '0') + "/";
+                        copyPath3 = copyPath2 + "\\" + j.ToString().PadLeft(2, '0');
+                        ftpHelper.GetDirctory(path3);
+                        List<string> dirctoryList3 = ftpHelper.GetDirctory(path3);
+                        max3 = getMaxNumber(dirctoryList3);
+                        if (j > int.Parse(level2Catalog))
+                        {
+                            level3Catalog = "0";
+                        }
+                        Log.Debug("secondCatalog:" + path3 + "max3-" + max3+ "level3Catalog" + level3Catalog);
+                        for (int l = int.Parse(level3Catalog); l <= max3; l++)
+                        {
+                            path4 = path3 + l.ToString().PadLeft(2, '0') + "/";
+                            copyPath4 = copyPath3 + "\\" + l.ToString().PadLeft(2, '0');
+                            Log.Info("开始从" + path4 + "复制录音文件");
+                            ftpHelper.DownFtp(path4, copyPath4);
+                        }
+                    }
+                }
+            }
+            else
+            {
+                List<string> filePathList = new List<string>();
+                FtpHelper ftpHelper = new FtpHelper();
+                ftpHelper.DownFtp(this.xmlBasePath, this.copyXmlFilePath);
+            }
+
+        }
+        // 获取当前路径下数量最大的文件夹名称
+        public int getMaxNumberDirectories(string path)
+        {
+            DirectoryInfo d = new DirectoryInfo(path);
+            DirectoryInfo[] directs = d.GetDirectories();//文件夹
+            int max = 0;
+            foreach (DirectoryInfo dd in directs)
+            {
+                int temp = int.Parse(dd.Name);
+                if (temp > max)
+                {
+                    max = temp;
+                }
+            }
+
+            return max;
+        }
+        // 获取当前路径下数量最大的文件夹名称
+        public int getMaxNumber(List<string> numberList)
+        {
+            int max = 0;
+            foreach (string number in numberList)
+            {
+                int temp = int.Parse(number);
+                if (temp > max)
+                {
+                    max = temp;
+                }
+            }
+            return max;
+        }
+        // 获取文件夹名
+        public List<string> GetDirectories(string dir, List<string> list)
+        {
+            DirectoryInfo d = new DirectoryInfo(dir);
+            FileInfo[] files = d.GetFiles();//文件
+            DirectoryInfo[] directs = d.GetDirectories();//文件夹
+            foreach (FileInfo f in files)
+            {
+                list.Add(f.FullName);//添加文件名到列表中  
+            }
+            //获取子文件夹内的文件列表,递归遍历  
+            foreach (DirectoryInfo dd in directs)
+            {
+                GetDirectories(dd.FullName, list);
+            }
+            return list;
+        }
+        /// <summary>
+        /// 将制定目录下的文件压缩为tar文件
+        /// </summary>
+        /// <param name="IN">源目录D:\\Images</param>
+        /// <param name="OUT">目标目录tar文件F:\\tar\\aaa.tar</param>
+        public static void CompressTarFile(string IN, string OUT)
+        {
+            Stream outStream = new FileStream(OUT, FileMode.OpenOrCreate);
+            TarArchive archive = TarArchive.CreateOutputTarArchive(outStream, TarBuffer.DefaultBlockFactor);
+            String[] files = Directory.GetFiles(IN);
+            foreach (String name in files)
+            {
+                TarEntry entry = TarEntry.CreateEntryFromFile(name);
+                entry.Name = name.Substring(name.LastIndexOf('\\') + 1);
+                archive.WriteEntry(entry, true);
+            }
+            if (archive != null)
+            {
+                archive.CloseArchive();
+            }
+        }
+        private DataTable getSqlField(OracleHelper oradb, DateTime minTime, DateTime maxTime)
+        {
+            string sql = string.Format("select r.recordno ID," +
+                "case when s3.workordertype3desc is null and s2.workordertype2desc is not null then s1.workordertype1desc || '_' || s2.workordertype2desc " +
+                "when s3.workordertype3desc is null and s2.workordertype2desc is null then substr(caltype, instr(caltype, '-', 1, 2) + 1, instr(caltype, '(') - 9) " +
+                "when ec.CALLNATUREGROUP_ID = 'FWF7RO' and e.calltype = '1' then substr(caltype, instr(caltype, '-', 1, 2) + 1, instr(caltype, '(') - 9)  " +
+                "else s1.workordertype1desc || '_' || s2.workordertype2desc || '_' || s3.workordertype3desc end 质检场景," +
+                "case when s.employeddate is null then '无入司时间'" +
+                "when floor(months_between(sysdate,s.employeddate)) >=0 and floor(months_between(sysdate,s.employeddate))< 3 then '三个月以内'" +
+                "when floor(months_between(sysdate,s.employeddate)) >=6 and floor(months_between(sysdate,s.employeddate))< 12 then '半年到一年'" +
+                "when floor(months_between(sysdate,s.employeddate)) >=12 and floor(months_between(sysdate,s.employeddate))< 24 then '一年到两年'" +
+                "else '两年及以上' end   入司时间,s.title 组别,decode(w.statisfaction1,'1','非常满意','2','满意','3','不满意','4','非常不满意','') 客户评价,c.fax 客户等级,c.homepage 客户类别," +
+                "s.staffname 坐席工号,s.agent_id 坐席id,t.businessno 业务号,r.initcallid callid from callcenter.record r " +
+                "left join callcenter.event e on e.event_guid = r.event_guid " +
+                "left join callcenter.tabccalsum t on t.relation_id = r.event_guid " +
+                "left join (select wm.event_guid,wm.statisfaction1,row_number() over(partition by wm.event_guid order by createddate) rn from wmsk_statisfaction wm) w on e.event_guid=w.event_guid " +
+                "left join callcenter.staff s on r.staff_id = s.staff_id " +
+                "left join callcenter.customer c on r.customer_guid = c.customer_guid " +
+                "left join callcenter.eventcallnature ec on ec.event_guid = r.event_guid " +
+                "left join callcenter.sys_workordertype1 s1 on s1.workordertype1_id = ec.callnaturegroup_id " +
+                "left join callcenter.sys_workordertype2 s2 on s2.workordertype2_id = ec.callnature_id " +
+                "left join callcenter.sys_workordertype3 s3 on s3.workordertype3_id = ec.callnature3_id " +
+                "left join callcenter.sys_workordertype4 s4 on s4.workordertype4_id = ec.callnature4_id " +
+                "left join callcenter.custom_parameter cp1 on cp1.parameter_id = t.producttype and cp1.parameter_type = 'producttype' " +
+                "where (w.rn=1 or w.rn is null) and " +
+                "r.starttime>=to_date('{0}','yyyy-mm-dd hh24:mi:ss') " +
+                "and r.starttime <= to_date('{1}','yyyy-mm-dd hh24:mi:ss')", minTime.ToString(), maxTime.ToString());
+            //string sql = string.Format("select * from TEST2");
+            DataTable data = oradb.GetDataTable(sql);
+            string idString = "";
+            for (int i = 0; i < data.Rows.Count; i++)
+            {
+                idString = idString + data.Rows[i]["callid"].ToString() + ",";//行集合.行【号】列【名】
+            }
+            Log.Debug("sql查询结果11为:" + idString);
+            return data;
+        }
+
+        public static string DeleteOneFile(string fileFullPath)
+        {
+            // 1、首先判断文件或者文件路径是否存在
+            if (Directory.Exists(fileFullPath))
+            {
+                // 2、根据路径字符串判断是文件还是文件夹
+                FileAttributes attr = File.GetAttributes(fileFullPath);
+                // 3、根据具体类型进行删除
+                if (attr == FileAttributes.Directory)
+                {
+                    Directory.Delete(fileFullPath, true); // 3.1、删除文件夹
+                }
+                else
+                {
+                    File.Delete(fileFullPath);// 3.2、删除文件
+                }
+                File.Delete(fileFullPath);
+                return "删除成功:" + fileFullPath;
+            }
+            return "无该文件或文件夹:" + fileFullPath;
+        }
+
+        // 删除某文件下超过days天的文件并且保留csv文件
+        public static void CleanCsvRecardFile(string folderPath, int days)
+        {
+            // 获取当前日期和时间
+            DateTime currentDate = DateTime.Now;
+
+            // 遍历文件夹中的所有文件
+            string[] files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);
+            foreach (string file in files)
+            {
+                // 获取文件最后写入时间
+                DateTime lastWriteTime = File.GetLastWriteTime(file);
+
+                // 获取文件拓展名
+                String fileExtension = Path.GetExtension(file);
+
+                // 计算最后写入时间与当前时间的差值
+                TimeSpan timeDifference = currentDate - lastWriteTime;
+
+                // 如果差值大于指定天数,则删除文件
+                if (timeDifference.TotalDays > days && fileExtension!=".csv")
+                {
+                    File.Delete(file);
+                    Console.WriteLine("Deleted file: " + file);
+                }
+            }
+        }
+    }
+}

+ 171 - 0
XmlDocumentAnalysis/XmlDocumentAnalysis.csproj

@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{BC61ED6A-AF0C-4DB9-8553-1F76F96AC0E6}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <RootNamespace>XmlDocumentAnalysis</RootNamespace>
+    <AssemblyName>XmlDocumentAnalysis</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <TargetFrameworkProfile />
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>1</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <PublishWizardCompleted>true</PublishWizardCompleted>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ManifestCertificateThumbprint>B9E9809F857E8D1CDC50CA2C38EA6553CF76BA21</ManifestCertificateThumbprint>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ManifestKeyFile>XmlDocumentAnalysis_TemporaryKey.pfx</ManifestKeyFile>
+  </PropertyGroup>
+  <PropertyGroup>
+    <GenerateManifests>true</GenerateManifests>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignManifests>false</SignManifests>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="ICSharpCode.SharpZipLib, Version=1.0.0.999, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
+      <HintPath>..\packages\SharpZipLib.1.0.0\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
+    </Reference>
+    <Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
+      <HintPath>..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.configuration" />
+    <Reference Include="System.Configuration.Install" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data.OracleClient" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Management" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Web.Extensions" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.ServiceProcess" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="FtpHelper.cs" />
+    <Compile Include="FileLastTimeComparer.cs" />
+    <Compile Include="Form1.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Form1.Designer.cs">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Log.cs" />
+    <Compile Include="model\XmlModel.cs" />
+    <Compile Include="OracleHelper.cs" />
+    <Compile Include="ProjectInstaller.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="ProjectInstaller.Designer.cs">
+      <DependentUpon>ProjectInstaller.cs</DependentUpon>
+    </Compile>
+    <Compile Include="XmlDocumentAnalysis.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="XmlDocumentAnalysis.Designer.cs">
+      <DependentUpon>XmlDocumentAnalysis.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="SQLHelper.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config">
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="Log4net.config">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="packages.config" />
+    <None Include="XmlDocumentAnalysis_TemporaryKey.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <WCFMetadata Include="Connected Services\" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Form1.resx">
+      <DependentUpon>Form1.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="ProjectInstaller.resx">
+      <DependentUpon>ProjectInstaller.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="XmlDocumentAnalysis.resx">
+      <DependentUpon>XmlDocumentAnalysis.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project>

+ 123 - 0
XmlDocumentAnalysis/XmlDocumentAnalysis.resx

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+</root>

+ 48 - 0
XmlDocumentAnalysis/model/XmlModel.cs

@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace XmlDucumentAnalysis.model
+{
+    public class XmlModel
+    {
+        public string recordingId { set; get; }
+
+        public string recordingFileName { set; get; }
+
+        public string dataPackage { set; get; }
+
+        public string duration { set; get; }
+
+        public string dateStartCall { set; get; }
+
+        public string dateHangup { set; get; }
+        public string callerNumber { set; get; }
+
+        public string destinationNumber { set; get; }
+
+        public string agentCti { set; get; }
+
+        public string agentId { set; get; }
+
+        public string sceneName { set; get; }
+
+        public string callType { set; get; }
+        public string customerId { set; get; }
+        public string platformCode { set; get; }
+        public string remark1 { set; get; }
+        public string remark2 { set; get; }
+        public string remark3 { set; get; }
+        public string remark4 { set; get; }
+        public string remark5 { set; get; }
+        public string remark6 { set; get; }
+        public string switch_call_id { set; get; }
+
+        internal void XmlFileAnalysis(string xmlFilePath)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 5 - 0
XmlDocumentAnalysis/packages.config

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="log4net" version="2.0.15" targetFramework="net452" />
+  <package id="SharpZipLib" version="1.0.0" targetFramework="net45" />
+</packages>