From 4dcc1158e1fb4afb557d2dd82c97fb0a2d8ea001 Mon Sep 17 00:00:00 2001 From: exsersewo Date: Tue, 29 Dec 2020 19:42:14 +0000 Subject: [PATCH] Tweak Gitignore --- src/{ => submodules/OPMLCore.NET}/.gitignore | 138 +++------- .../OPMLCore.NET/.vscode/launch.json | 29 ++ .../OPMLCore.NET/.vscode/tasks.json | 15 ++ src/submodules/OPMLCore.NET/LICENSE | 21 ++ .../OPMLCore.NET/OPMLCoredotNET.sln | 53 ++++ src/submodules/OPMLCore.NET/README.md | 48 ++++ .../OPMLCore.NET/src/OPMLCore.NET/Body.cs | 52 ++++ .../OPMLCore.NET/src/OPMLCore.NET/Head.cs | 213 +++++++++++++++ .../src/OPMLCore.NET/OPMLCore.NET.csproj | 7 + .../OPMLCore.NET/src/OPMLCore.NET/Opml.cs | 93 +++++++ .../OPMLCore.NET/src/OPMLCore.NET/Outline.cs | 203 ++++++++++++++ src/submodules/OPMLCore.NET/test/UnitTest1.cs | 251 ++++++++++++++++++ src/submodules/OPMLCore.NET/test/test.csproj | 20 ++ 13 files changed, 1048 insertions(+), 95 deletions(-) rename src/{ => submodules/OPMLCore.NET}/.gitignore (69%) create mode 100644 src/submodules/OPMLCore.NET/.vscode/launch.json create mode 100644 src/submodules/OPMLCore.NET/.vscode/tasks.json create mode 100644 src/submodules/OPMLCore.NET/LICENSE create mode 100644 src/submodules/OPMLCore.NET/OPMLCoredotNET.sln create mode 100644 src/submodules/OPMLCore.NET/README.md create mode 100644 src/submodules/OPMLCore.NET/src/OPMLCore.NET/Body.cs create mode 100644 src/submodules/OPMLCore.NET/src/OPMLCore.NET/Head.cs create mode 100644 src/submodules/OPMLCore.NET/src/OPMLCore.NET/OPMLCore.NET.csproj create mode 100644 src/submodules/OPMLCore.NET/src/OPMLCore.NET/Opml.cs create mode 100644 src/submodules/OPMLCore.NET/src/OPMLCore.NET/Outline.cs create mode 100644 src/submodules/OPMLCore.NET/test/UnitTest1.cs create mode 100644 src/submodules/OPMLCore.NET/test/test.csproj diff --git a/src/.gitignore b/src/submodules/OPMLCore.NET/.gitignore similarity index 69% rename from src/.gitignore rename to src/submodules/OPMLCore.NET/.gitignore index c779b69..6edac65 100644 --- a/src/.gitignore +++ b/src/submodules/OPMLCore.NET/.gitignore @@ -1,10 +1,21 @@ + +# Created by https://www.gitignore.io/api/visualstudio,visualstudiocode + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history + +### VisualStudio ### ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files -*.rsuser *.suo *.user *.userosscache @@ -13,9 +24,6 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs -# Mono auto generated files -mono_crash.* - # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -23,62 +31,43 @@ mono_crash.* [Rr]eleases/ x64/ x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ -[Ll]ogs/ -# Visual Studio 2015/2017 cache/options directory +# Visual Studio 2015 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ -# Visual Studio 2017 auto generated files -Generated\ Files/ - # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -# NUnit +# NUNIT *.VisualState.xml TestResult.xml -nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c -# Benchmark Results -BenchmarkDotNet.Artifacts/ - # .NET Core project.lock.json project.fragment.lock.json artifacts/ +**/Properties/launchSettings.json -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio *_i.c *_p.c -*_h.h +*_i.h *.ilk *.meta *.obj -*.iobj *.pch *.pdb -*.ipdb *.pgc *.pgd *.rsp @@ -88,7 +77,6 @@ StyleCopReport.xml *.tlh *.tmp *.tmp_proj -*_wpftmp.csproj *.log *.vspscc *.vssscc @@ -117,9 +105,6 @@ ipch/ *.vspx *.sap -# Visual Studio Trace Files -*.e2e - # TFS 2012 Local Workspace $tf/ @@ -131,21 +116,15 @@ _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 -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - # Visual Studio code coverage results *.coverage *.coveragexml @@ -181,9 +160,11 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml +# TODO: Uncomment the next line to ignore your web deploy settings. +# By default, sensitive information, such as encrypted password +# should be stored in the .pubxml.user file. +#*.pubxml +*.pubxml.user *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to @@ -193,14 +174,12 @@ PublishScripts/ # NuGet Packages *.nupkg -# NuGet Symbol Packages -*.snupkg # The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* +**/packages/* # except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ +!**/packages/build/ # Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config +#!**/packages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets @@ -218,15 +197,12 @@ AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt -*.appx -*.appxbundle -*.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache -!?*.[Cc]ache/ +!*.[Cc]ache/ # Others ClientBin/ @@ -239,10 +215,6 @@ ClientBin/ *.publishsettings orleans.codegen.cs -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ @@ -257,8 +229,6 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak # SQL Server files *.mdf @@ -269,10 +239,6 @@ ServiceFabricBackup/ *.rdl.data *.bim.layout *.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ @@ -284,6 +250,9 @@ FakesAssemblies/ .ntvs_analysis.dat node_modules/ +# Typescript v1 declaration files +typings/ + # Visual Studio 6 build log *.plg @@ -308,8 +277,12 @@ paket-files/ # FAKE - F# Make .fake/ -# CodeRush personal settings -.cr/personal +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ @@ -319,9 +292,6 @@ __pycache__/ # tools/** # !tools/packages.config -# Tabs Studio -*.tss - # Telerik's JustMock configuration file *.jmconfig @@ -331,34 +301,12 @@ __pycache__/ *.odx.cs *.xsd.cs -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ +### VisualStudio Patch ### +# By default, sensitive information, such as encrypted password +# should be stored in the .pubxml.user file. -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ -# Fody - auto-generated XML schema -FodyWeavers.xsd +# End of https://www.gitignore.io/api/visualstudio,visualstudiocode -[Ss]ubmodules/* \ No newline at end of file +# Mac +.DS_Store diff --git a/src/submodules/OPMLCore.NET/.vscode/launch.json b/src/submodules/OPMLCore.NET/.vscode/launch.json new file mode 100644 index 0000000..3451294 --- /dev/null +++ b/src/submodules/OPMLCore.NET/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/test.xunit/bin/Debug/netcoreapp2.0/test.xunit.dll", + "args": [], + "cwd": "${workspaceFolder}/test.xunit", + // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window + "console": "internalConsole", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ,] +} \ No newline at end of file diff --git a/src/submodules/OPMLCore.NET/.vscode/tasks.json b/src/submodules/OPMLCore.NET/.vscode/tasks.json new file mode 100644 index 0000000..3724a42 --- /dev/null +++ b/src/submodules/OPMLCore.NET/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/test.xunit/test.xunit.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/src/submodules/OPMLCore.NET/LICENSE b/src/submodules/OPMLCore.NET/LICENSE new file mode 100644 index 0000000..0d1fa8d --- /dev/null +++ b/src/submodules/OPMLCore.NET/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 fnya + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/submodules/OPMLCore.NET/OPMLCoredotNET.sln b/src/submodules/OPMLCore.NET/OPMLCoredotNET.sln new file mode 100644 index 0000000..3bdd659 --- /dev/null +++ b/src/submodules/OPMLCore.NET/OPMLCoredotNET.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0DA6DFA3-972E-4B42-AF2C-67D226DCDD89}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OPMLCore.NET", "src\OPMLCore.NET\OPMLCore.NET.csproj", "{74D51452-48A8-4F0F-82B5-F47826B4F1C9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test", "test\test.csproj", "{15E07BD7-75A1-46F8-8697-F146915FC23F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Debug|x64.ActiveCfg = Debug|x64 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Debug|x64.Build.0 = Debug|x64 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Debug|x86.ActiveCfg = Debug|x86 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Debug|x86.Build.0 = Debug|x86 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Release|Any CPU.Build.0 = Release|Any CPU + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Release|x64.ActiveCfg = Release|x64 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Release|x64.Build.0 = Release|x64 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Release|x86.ActiveCfg = Release|x86 + {74D51452-48A8-4F0F-82B5-F47826B4F1C9}.Release|x86.Build.0 = Release|x86 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Debug|x64.ActiveCfg = Debug|x64 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Debug|x64.Build.0 = Debug|x64 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Debug|x86.ActiveCfg = Debug|x86 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Debug|x86.Build.0 = Debug|x86 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Release|Any CPU.Build.0 = Release|Any CPU + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Release|x64.ActiveCfg = Release|x64 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Release|x64.Build.0 = Release|x64 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Release|x86.ActiveCfg = Release|x86 + {15E07BD7-75A1-46F8-8697-F146915FC23F}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {74D51452-48A8-4F0F-82B5-F47826B4F1C9} = {0DA6DFA3-972E-4B42-AF2C-67D226DCDD89} + EndGlobalSection +EndGlobal diff --git a/src/submodules/OPMLCore.NET/README.md b/src/submodules/OPMLCore.NET/README.md new file mode 100644 index 0000000..38b2afc --- /dev/null +++ b/src/submodules/OPMLCore.NET/README.md @@ -0,0 +1,48 @@ +# OPMLCore.NET +OPMLCore.NET is OPML Parser which easy to use for .NET Core Applications. + +It is written in C# and with Visual Studio Code. + +It supports .NET Core 2.0. + +# Setting + +You shoud add project refference to your project. + +The below is sample `.csproj` which is added project refference. + +``` + + + +``` +And then `dotnet restore`. + +# Usage + How to use is below. + +``` +using OPMLCore.NET; //Add + +Opml opml = new Opml("opmlFilePath"); + +foreach (Outline outline in opml.Body.Outlines) +{ + //Output outline node + Console.WriteLine(outline.Text); + Console.WriteLine(outline.XMLUrl); + + //output child's output node + foreach (Outline childOutline in outline.Outlines) + { + Console.WriteLine(childOutline.Text); + Console.WriteLine(childOutline.XMLUrl); + } +} + +``` + +For more detail, show test code or source code. + +# License +Lisense is MIT License. diff --git a/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Body.cs b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Body.cs new file mode 100644 index 0000000..bbcce35 --- /dev/null +++ b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Body.cs @@ -0,0 +1,52 @@ +using System; +using System.Text; +using System.Xml; +using System.Collections.Generic; + +namespace OPMLCore.NET { + public class Body + { + /// + /// Outline list + /// + public List Outlines { get; set; } = new List(); + + /// + /// Constructor + /// + public Body() + { + + } + + /// + /// Constructor + /// + /// element of Body + public Body(XmlElement element) + { + if (element.Name.Equals("body", StringComparison.CurrentCultureIgnoreCase)) + { + foreach (XmlNode node in element.ChildNodes) + { + if (node.Name.Equals("outline", StringComparison.CurrentCultureIgnoreCase)) + { + Outlines.Add(new Outline((XmlElement)node)); + } + } + } + } + + public override string ToString() { + StringBuilder buf = new StringBuilder(); + buf.Append("\r\n"); + foreach (Outline outline in Outlines) + { + buf.Append(outline.ToString()); + } + buf.Append("\r\n"); + + return buf.ToString(); + } + } +} \ No newline at end of file diff --git a/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Head.cs b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Head.cs new file mode 100644 index 0000000..7cb72f0 --- /dev/null +++ b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Head.cs @@ -0,0 +1,213 @@ +using System; +using System.Text; +using System.Xml; +using System.Collections.Generic; + +namespace OPMLCore.NET { + public class Head + { + /// + /// title + /// + public string Title { get; set; } + + /// + /// Created date + /// + public DateTime? DateCreated { get; set; } = null; + + /// + /// Modified date + /// + public DateTime? DateModified { get; set; } = null; + + /// + /// ownerName + /// + public string OwnerName { get; set; } + + /// + /// ownerEmail + /// + public string OwnerEmail { get; set; } + + /// + /// ownerId + /// + public string OwnerId { get; set;} + + /// + /// docs + /// + public string Docs { get; set;} + + /// + /// expansionState + /// + public List ExpansionState { get; set; } = new List(); + + /// + /// vertScrollState + /// + public string VertScrollState { get; set; } + + /// + /// windowTop + /// + public string WindowTop { get; set; } + + /// + /// windowLeft + /// + public string WindowLeft { get; set; } + + /// + /// windowBottom + /// + public string WindowBottom { get; set; } + + /// + /// windowRight + /// + public string WindowRight { get; set; } + + /// + /// Constructor + /// + public Head() + { + + } + + /// + /// Constructor + /// + /// element of Head + public Head(XmlElement element) + { + if (element.Name.Equals("head", StringComparison.CurrentCultureIgnoreCase)) + { + foreach (XmlNode node in element.ChildNodes) + { + Title = GetStringValue(node, "title", Title); + DateCreated = GetDateTimeValue(node, "dateCreated", DateCreated); + DateModified = GetDateTimeValue(node, "dateModified", DateModified); + OwnerName = GetStringValue(node, "ownerName", OwnerName); + OwnerEmail = GetStringValue(node, "ownerEmail", OwnerEmail); + OwnerId = GetStringValue(node, "ownerId", OwnerId); + Docs = GetStringValue(node, "docs", Docs); + ExpansionState = GetExpansionState(node, "expansionState", ExpansionState); + VertScrollState = GetStringValue(node, "vertScrollState", VertScrollState); + WindowTop = GetStringValue(node, "windowTop", WindowTop); + WindowLeft = GetStringValue(node, "windowLeft", WindowLeft); + WindowBottom = GetStringValue(node, "windowBottom", WindowBottom); + WindowRight = GetStringValue(node, "windowRight", WindowRight); + } + } + } + + private string GetStringValue(XmlNode node, string name, string value) + { + if (node.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)) + { + return node.InnerText; + } else if (!node.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)) { + return value; + } else { + return string.Empty; + } + } + + private DateTime? GetDateTimeValue(XmlNode node, string name, DateTime? value) + { + if (node.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)) + { + try { + return DateTime.Parse(node.InnerText); + } catch { + return null; + } + } else if (!node.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)){ + return value; + } else { + return null; + } + } + + private List GetExpansionState(XmlNode node, string name, List value) + { + if (node.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)) + { + List list = new List(); + var items = node.InnerText.Split(','); + foreach(var item in items) + { + list.Add(item.Trim()); + } + return list; + + } else if (!node.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase)) + { + return value; + } else { + return new List(); + } + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + buf.Append("\r\n"); + buf.Append(GetNodeString("title", Title)); + buf.Append(GetNodeString("dateCreated", DateCreated)); + buf.Append(GetNodeString("dateModified", DateModified)); + buf.Append(GetNodeString("ownerName", OwnerName)); + buf.Append(GetNodeString("ownerEmail", OwnerEmail)); + buf.Append(GetNodeString("ownerId", OwnerId)); + buf.Append(GetNodeString("docs", Docs)); + buf.Append(GetNodeString("expansionState", ExpansionState)); + buf.Append(GetNodeString("vertScrollState", VertScrollState)); + buf.Append(GetNodeString("windowTop", WindowTop)); + buf.Append(GetNodeString("windowLeft", WindowLeft)); + buf.Append(GetNodeString("windowBottom", WindowBottom)); + buf.Append(GetNodeString("windowRight", WindowRight)); + buf.Append("\r\n"); + return buf.ToString(); + } + + private string GetNodeString(string name, string value) + { + if (string.IsNullOrEmpty(value)) + { + return string.Empty; + } else { + return $"<{name}>{value}\r\n"; + } + } + private string GetNodeString(string name, DateTime? value) + { + if (value == null) + { + return string.Empty; + } else { + return $"<{name}>{value?.ToString("R")}\r\n"; + } + } + + private string GetNodeString(string name, List value) + { + if (value.Count == 0) { + return string.Empty; + } + + StringBuilder buf = new StringBuilder(); + foreach (var item in value) + { + buf.Append(item); + buf.Append(","); + } + + return $"<{name}>{buf.Remove(buf.Length - 1, 1).ToString()}\r\n"; + } + } +} \ No newline at end of file diff --git a/src/submodules/OPMLCore.NET/src/OPMLCore.NET/OPMLCore.NET.csproj b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/OPMLCore.NET.csproj new file mode 100644 index 0000000..9f5c4f4 --- /dev/null +++ b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/OPMLCore.NET.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Opml.cs b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Opml.cs new file mode 100644 index 0000000..d82be9a --- /dev/null +++ b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Opml.cs @@ -0,0 +1,93 @@ +using System; +using System.Text; +using System.Xml; + +namespace OPMLCore.NET { + public class Opml { + /// + /// Version of OPML + /// + public string Version { get; set;} + + /// + /// Encoding of OPML + /// + public string Encoding { get; set;} + + /// + /// Head of OPML + /// + public Head Head { get; set;} = new Head(); + + /// + /// Body of OPML + /// + public Body Body { get; set;} = new Body(); + + /// + /// Constructor + /// + public Opml() + { + + } + + /// + /// Constructor + /// + /// Location of the OPML file + public Opml(string location) + { + XmlDocument doc = new XmlDocument(); + doc.Load(location); + readOpmlNodes(doc); + } + + /// + /// Constructor + /// + /// XMLDocument of the OPML + public Opml(XmlDocument doc) + { + readOpmlNodes(doc); + } + + + private void readOpmlNodes(XmlDocument doc) { + foreach (XmlNode nodes in doc) + { + if (nodes.Name.Equals("opml", StringComparison.CurrentCultureIgnoreCase)) + { + foreach (XmlNode childNode in nodes) + { + + if (childNode.Name.Equals("head", StringComparison.CurrentCultureIgnoreCase)) + { + Head = new Head((XmlElement) childNode); + } + + if (childNode.Name.Equals("body", StringComparison.CurrentCultureIgnoreCase)) + { + Body = new Body((XmlElement) childNode); + } + } + } + } + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + String ecoding = string.IsNullOrEmpty(Encoding)?"UTF-8":Encoding; + buf.Append($"\r\n"); + String version = string.IsNullOrEmpty(Version)?"2.0":Version; + buf.Append($"\r\n"); + buf.Append(Head.ToString()); + buf.Append(Body.ToString()); + buf.Append(""); + + return buf.ToString(); + } + + } +} \ No newline at end of file diff --git a/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Outline.cs b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Outline.cs new file mode 100644 index 0000000..99ceebe --- /dev/null +++ b/src/submodules/OPMLCore.NET/src/OPMLCore.NET/Outline.cs @@ -0,0 +1,203 @@ +using System; +using System.Text; +using System.Xml; +using System.Collections.Generic; + +namespace OPMLCore.NET { + public class Outline + { + /// + /// Text of the XML file (required) + /// + public string Text { get; set; } + + /// + /// true / false + /// + public string IsComment { get; set; } + + /// + /// true / false + /// + public string IsBreakpoint { get; set; } + + /// + /// outline node was created + /// + public DateTime? Created { get; set; } = null; + + /// + /// Categories + /// + public List Category { get; set; } = new List(); + + /// + /// Description + /// + public string Description { get; set; } + + /// + /// HTML URL + /// + public string HTMLUrl { get; set; } + + /// + /// Language + /// + public string Language { get; set; } + + /// + /// Title + /// + public string Title { get; set; } + + /// + /// Type (rss/atom) + /// + public string Type { get; set; } + + /// + /// Version of RSS. + /// RSS1 for RSS1.0. RSS for 0.91, 0.92 or 2.0. + /// + public string Version { get; set; } + + /// + /// URL of the XML file + /// + public string XMLUrl { get; set; } + + /// + /// Outline list + /// + public List Outlines { get; set; } = new List(); + + /// + /// Constructor + /// + public Outline() + { + + } + + + /// + /// Constructor + /// + /// element of Head + public Outline(XmlElement element) + { + Text = element.GetAttribute("text"); + IsComment = element.GetAttribute("isComment"); + IsBreakpoint = element.GetAttribute("isBreakpoint"); + Created = GetDateTimeAttribute(element, "created"); + Category = GetCategoriesAtrribute(element, "category"); + Description = element.GetAttribute("description"); + HTMLUrl = element.GetAttribute("htmlUrl"); + Language = element.GetAttribute("language"); + Title = element.GetAttribute("title"); + Type = element.GetAttribute("type"); + Version = element.GetAttribute("version"); + XMLUrl = element.GetAttribute("xmlUrl"); + + if (element.HasChildNodes) { + foreach (XmlNode child in element.ChildNodes) + { + if (child.Name.Equals("outline", StringComparison.CurrentCultureIgnoreCase)) + { + Outlines.Add(new Outline((XmlElement) child)); + } + } + } + } + + private DateTime? GetDateTimeAttribute(XmlElement element, string name) + { + string dt = element.GetAttribute(name); + + try { + return DateTime.Parse(dt); + } catch { + return null; + } + } + + private List GetCategoriesAtrribute(XmlElement element, string name) + { + List list = new List(); + var items = element.GetAttribute(name).Split(','); + foreach(var item in items) + { + list.Add(item.Trim()); + } + return list; + } + + public override string ToString() + { + StringBuilder buf = new StringBuilder(); + buf.Append(" 0) + { + buf.Append(">\r\n"); + foreach (Outline outline in Outlines) + { + buf.Append(outline.ToString()); + } + buf.Append("\r\n"); + } else { + buf.Append(" />\r\n"); + } + return buf.ToString(); + } + + private string GetAtrributeString(string name, string value) + { + if (string.IsNullOrEmpty(value)) + { + return string.Empty; + } else { + return $" {name}=\"{value}\""; + } + } + + private string GetAtrributeString(string name, DateTime? value) + { + if (value == null) + { + return string.Empty; + } else { + return $" {name}=\"{value?.ToString("R")}\""; + } + } + + private string GetAtrributeString(string name, List value) + { + if (value.Count == 0) { + return string.Empty; + } + + StringBuilder buf = new StringBuilder(); + foreach (var item in value) + { + buf.Append(item); + buf.Append(","); + } + + return $" {name}=\"{buf.Remove(buf.Length - 1, 1).ToString()}\""; + } + } +} \ No newline at end of file diff --git a/src/submodules/OPMLCore.NET/test/UnitTest1.cs b/src/submodules/OPMLCore.NET/test/UnitTest1.cs new file mode 100644 index 0000000..3dba2d7 --- /dev/null +++ b/src/submodules/OPMLCore.NET/test/UnitTest1.cs @@ -0,0 +1,251 @@ +using System; +using System.Linq; +using System.Text; +using System.Xml; +using Xunit; +using OPMLCore.NET; + +namespace test +{ + public class UnitTest1 + { + [Fact] + public void NormalTest() + { + StringBuilder xml = new StringBuilder(); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append("mySubscriptions.opml"); + xml.Append("Sat, 18 Jun 2005 12:11:52 GMT"); + xml.Append("Tue, 02 Aug 2005 21:42:48 GMT"); + xml.Append("fnya"); + xml.Append("fnya@example.com"); + xml.Append("http://news.com.com/"); + xml.Append("http://news.com.com/"); + xml.Append("1, 6, 13, 16, 18, 20"); + xml.Append("1"); + xml.Append("106"); + xml.Append("106"); + xml.Append("558"); + xml.Append("479"); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append(""); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml.ToString()); + Opml opml = new Opml(doc); + + Assert.True(opml.Head.Title == "mySubscriptions.opml"); + Assert.True(opml.Head.DateCreated == DateTime.Parse("Sat, 18 Jun 2005 12:11:52 GMT")); + Assert.True(opml.Head.DateModified == DateTime.Parse("Tue, 02 Aug 2005 21:42:48 GMT")); + Assert.True(opml.Head.OwnerName == "fnya"); + Assert.True(opml.Head.OwnerEmail == "fnya@example.com"); + Assert.True(opml.Head.OwnerId == "http://news.com.com/"); + Assert.True(opml.Head.Docs == "http://news.com.com/"); + Assert.True(opml.Head.ExpansionState.ToArray().SequenceEqual("1,6,13,16,18,20".Split(','))); + Assert.True(opml.Head.VertScrollState == "1"); + Assert.True(opml.Head.WindowTop == "106"); + Assert.True(opml.Head.WindowLeft == "106"); + Assert.True(opml.Head.WindowBottom == "558"); + Assert.True(opml.Head.WindowRight == "479"); + + foreach (var outline in opml.Body.Outlines) + { + Assert.True(outline.Text == "CNET News.com"); + Assert.True(outline.IsComment == "true"); + Assert.True(outline.IsBreakpoint == "true"); + Assert.True(outline.Created == DateTime.Parse("Tue, 02 Aug 2005 21:42:48 GMT")); + Assert.True(outline.Category.ToArray().SequenceEqual("/Harvard/Berkman,/Politics".Split(','))); + Assert.True(outline.Description == "Tech news and business reports by CNET News.com."); + Assert.True(outline.HTMLUrl == "http://news.com.com/"); + Assert.True(outline.Language == "unknown"); + Assert.True(outline.Title == "CNET News.com"); + Assert.True(outline.Type == "rss"); + Assert.True(outline.Version == "RSS2"); + Assert.True(outline.XMLUrl == "http://news.com.com/2547-1_3-0-5.xml"); + } + } + + [Fact] + public void ChildNodeTest() + { + StringBuilder xml = new StringBuilder(); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append("mySubscriptions.opml"); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append(""); + xml.Append(""); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml.ToString()); + Opml opml = new Opml(doc); + + foreach (var outline in opml.Body.Outlines) + { + foreach(var childOutline in outline.Outlines) { + Assert.True(childOutline.Text == "washingtonpost.com"); + Assert.True(childOutline.HTMLUrl == "http://www.washingtonpost.com"); + Assert.True(childOutline.XMLUrl == "http://www.washingtonpost.com/rss.xml"); + } + } + } + + [Fact] + public void CreateNormalOpmlTest() + { + Opml opml = new Opml(); + opml.Encoding = "UTF-8"; + opml.Version = "2.0"; + + Head head = new Head(); + head.Title = "mySubscriptions.opml"; + head.DateCreated = DateTime.Parse("Sat, 18 Jun 2005 12:11:52 GMT").ToUniversalTime(); + head.DateModified = DateTime.Parse("Tue, 02 Aug 2005 21:42:48 GMT").ToUniversalTime(); + head.OwnerName = "fnya"; + head.OwnerEmail = "fnya@example.com"; + head.OwnerId = "http://news.com.com/"; + head.Docs = "http://news.com.com/"; + head.ExpansionState.Add("1"); + head.ExpansionState.Add("6"); + head.ExpansionState.Add("13"); + head.ExpansionState.Add("16"); + head.ExpansionState.Add("18"); + head.ExpansionState.Add("20"); + head.VertScrollState = "1"; + head.WindowTop = "106"; + head.WindowLeft = "106"; + head.WindowBottom = "558"; + head.WindowRight = "479"; + opml.Head = head; + + Outline outline = new Outline(); + outline.Text = "CNET News.com"; + outline.IsComment = "true"; + outline.IsBreakpoint = "true"; + outline.Created = DateTime.Parse("Tue, 02 Aug 2005 21:42:48 GMT").ToUniversalTime(); + outline.Category.Add("/Harvard/Berkman"); + outline.Category.Add("/Politics"); + outline.Description = "Tech news and business reports by CNET News.com."; + outline.HTMLUrl = "http://news.com.com/"; + outline.Language = "unknown"; + outline.Title = "CNET News.com"; + outline.Type = "rss"; + outline.Version = "RSS2"; + outline.XMLUrl = "http://news.com.com/2547-1_3-0-5.xml"; + + Body body = new Body(); + body.Outlines.Add(outline); + opml.Body = body; + + StringBuilder xml = new StringBuilder(); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("mySubscriptions.opml\r\n"); + xml.Append("Sat, 18 Jun 2005 12:11:52 GMT\r\n"); + xml.Append("Tue, 02 Aug 2005 21:42:48 GMT\r\n"); + xml.Append("fnya\r\n"); + xml.Append("fnya@example.com\r\n"); + xml.Append("http://news.com.com/\r\n"); + xml.Append("http://news.com.com/\r\n"); + xml.Append("1,6,13,16,18,20\r\n"); + xml.Append("1\r\n"); + xml.Append("106\r\n"); + xml.Append("106\r\n"); + xml.Append("558\r\n"); + xml.Append("479\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append(""); + + Assert.True(opml.ToString() == xml.ToString()); + + } + + [Fact] + public void CreateChildOpmlTest() + { + Opml opml = new Opml(); + opml.Encoding = "UTF-8"; + opml.Version = "2.0"; + + Head head = new Head(); + head.Title = "mySubscriptions.opml"; + opml.Head = head; + + Outline outline = new Outline(); + outline.Text = "IT"; + + Outline childOutline = new Outline(); + childOutline.Text = "CNET News.com"; + childOutline.HTMLUrl = "http://news.com.com/"; + childOutline.XMLUrl = "http://news.com.com/2547-1_3-0-5.xml"; + + outline.Outlines.Add(childOutline); + + Body body = new Body(); + body.Outlines.Add(outline); + opml.Body = body; + + StringBuilder xml = new StringBuilder(); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("mySubscriptions.opml\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append("\r\n"); + xml.Append(""); + + Assert.True(opml.ToString() == xml.ToString()); + } + } +} diff --git a/src/submodules/OPMLCore.NET/test/test.csproj b/src/submodules/OPMLCore.NET/test/test.csproj new file mode 100644 index 0000000..37ebc6e --- /dev/null +++ b/src/submodules/OPMLCore.NET/test/test.csproj @@ -0,0 +1,20 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + +