This commit is contained in:
Florian Rappl 2019-01-07 00:49:00 +01:00
Коммит 4870acc012
75 изменённых файлов: 18557 добавлений и 0 удалений

13
.editorconfig Normal file
Просмотреть файл

@ -0,0 +1,13 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
[*.csproj]
indent_style = space
indent_size = 2

22
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.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

46
.github/CODE_OF_CONDUCT.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

126
.github/CONTRIBUTING.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,126 @@
# Contributing
## Project Scope
The AngleSharp project ultimately tries to provide tools to parse, inspect, modify and interact with traditional web resources, such as HTML or CSS, for .NET development. Anything that is related to this goal will be considered. The project aims to be fully standards compliant. If your contribution is not following the standard, the chances of accepting it are limited.
## Code License
This is an open source project falling under the MIT License. By using, distributing, or contributing to this project, you accept and agree that all code within the AngleSharp project are licensed under MIT license.
## Becoming a Contributor
Until the project has enough contributors a BDFL model is followed. As such the sole key maintainer keeps the right to appoint GitHub members as regular project contributors. Nevertheless, usually appointing someone follows this process:
1. An individual contributes actively via discussions (reporting bugs, giving feedback to existing or opening new issues) and / or pull requests
2. The individual is either directly asked, invited or asks for contributor rights on the project
3. The individual uses the contribution rights to sustain or increase the active contributions
Every contributor has to sign the contributor's license agreement (CLA) to establish a legal trust between the project and its contributors.
## Working on AngleSharp
### Issue Discussion
Discussion of issues should be placed transparently in the [issue tracker](https://github.com/FlorianRappl/AngleSharp/issues/) here on GitHub.
### Modifying the code
AngleSharp uses features from C# 6 and will soon switch to C# 7. You will therefore need a C# compiler that is up for the job.
1. Fork and clone the repo.
2. First try to build the AngleSharp.Core libray and see if you get the tests running.
3. You will be required to resolve some dependencies via NuGet.
AngleSharp itself does not have dependencies, however, the tests are dependent on NUnit.
The build system of AngleSharp uses Cake. A bootstrap script (build.ps1 for Windows or build.sh for *nix systems) is included. Note, that at the moment AngleSharp requires NuGet 3.5, which looks for MSBuild pre-15, i.e., before Visual Studio 2017 on Windows systems.
### Code Conventions
Most parts in the AngleSharp project are fairly straight forward. Among these are:
- Always use statement blocks for control statements, e.g., in a for-loop, if-condition, ...
- You may use a simple (throw) statement in case of enforcing contracts on argument
- Be explicit about modifiers (some files follow an older convention of the code base, but we settled on the explicit style)
There are a couple of rules, which are definitely not standard, but highly recommended for consistency and readability:
- AngleSharp uses the RHS convention, where types are always put on the right hand side if possible, i.e., preferring `var` under all circumstances
- A single empty line between two non-simple statements (e.g., for-loop and if-condition) should be inserted
- Types are preferred to keywords (`String` instead of `string` or `Int32` instead of `int`)
### Development Workflow
1. If no issue already exists for the work you'll be doing, create one to document the problem(s) being solved and self-assign.
2. Otherwise please let us know that you are working on the problem. Regular status updates (e.g. "still in progress", "no time anymore", "practically done", "pull request issued") are highly welcome.
2. Create a new branch—please don't work in the `master` branch directly. It is reserved for releases. We recommend naming the branch to match the issue being addressed (`feature-#777` or `issue-777`).
3. Add failing tests for the change you want to make. Tests are crucial and should be taken from W3C (or other specification).
4. Fix stuff. Always go from edge case to edge case.
5. All tests should pass now. Also your new implementation should not break existing tests.
6. Update the documentation to reflect any changes. (or document such changes in the original issue)
7. Push to your fork or push your issue-specific branch to the main repository, then submit a pull request against `devel`.
Just to illustrate the git workflow for AngleSharp a little bit more we've added the following graphs.
Initially AngleSharp starts at the `master` branch. This branch should contain the latest stable (or released) version.
![AngleSharp Initial Master](https://github.com/AngleSharp/AngleSharp/wiki/initial-master.png)
Here we now created a new branch called `devel`. This is the development branch.
![AngleSharp Initial Devel](https://github.com/AngleSharp/AngleSharp/wiki/initial-devel.png)
Now active work is supposed to be done. Therefore a new branch should be created. Let's create one:
git checkout -b feature-#777
There may be many of these feature branches. Most of them are also pushed to the server for discussion or synchronization.
git push -u origin feature-#777
At this point the graph could look as follows. The diagram shows two feature branches in different stages.
![AngleSharp Feature Branches](https://github.com/AngleSharp/AngleSharp/wiki/feature-branches.png)
Now feature branches may be closed when they are done. Here we simply merge with the feature branch(es). For instance the following command takes the `feature-#777` branch from the server and merges it with the `devel` branch.
git checkout devel
git pull
git pull origin feature-#777
git push
This aggregates to the graph below.
![AngleSharp Merge Branches](https://github.com/AngleSharp/AngleSharp/wiki/feature-merges.png)
Finally we may have all the features that are needed to release a new version of AngleSharp. Here we tag the release. For instance for the 1.0 release we use `v1.0`.
git checkout master
git merge devel
git tag v1.0
Hence finally we have the full graph.
![AngleSharp Release Git Graph](https://github.com/AngleSharp/AngleSharp/wiki/release.png)
### Versioning
The rules of [semver](http://semver.org/) don't necessarily apply here, but we will try to stay quite close to them.
Prior to version 1.0.0 we use the following scheme:
1. MINOR versions for reaching a feature milestone potentially combined with dramatic API changes
2. PATCH versions for refinements (e.g. performance improvements, bug fixes)
After releasing version 1.0.0 the scheme changes to become:
1. MAJOR versions at maintainers' discretion following significant changes to the codebase (e.g., API changes)
2. MINOR versions for backwards-compatible enhancements (e.g., performance improvements)
3. PATCH versions for backwards-compatible bug fixes (e.g., spec compliance bugs, support issues)
#### Code style
Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.** In general most of the [C# coding guidelines from Microsoft](https://msdn.microsoft.com/en-us/library/ff926074.aspx) are followed. This project prefers type inference with `var` to explicitly stating (redundant) information.
It is also important to keep a certain `async`-flow and to always use `ConfigureAwait(false)` in conjunction with an `await` expression.

6
.github/ISSUE_TEMPLATE.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
# Issue Templates
Please use one of the following templates to create your issue:
- [BUG REPORT](https://github.com/AngleSharp/AngleSharp.Xml/issues/new?template=bugs.md)
- [FEATURE PROPOSAL](https://github.com/AngleSharp/AngleSharp.Xml/issues/new?template=features.md)

31
.github/ISSUE_TEMPLATE/bugs.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,31 @@
## Bug Report
### Prerequisites
- [ ] Can you reproduce the problem in a [MWE](https://en.wikipedia.org/wiki/Minimal_working_example)?
- [ ] Are you running the latest version of AngleSharp?
- [ ] Did you check the FAQs to see if that helps you?
- [ ] Are you reporting to the correct repository? (if its an issue with the core library, please report to `AngleSharp` directly)
- [ ] Did you perform a search in the issues?
For more information, see the `CONTRIBUTING` guide.
### Description
[Description of the bug]
### Steps to Reproduce
1. [First Step]
2. [Second Step]
3. [and so on...]
**Expected behavior:** [What you expected to happen]
**Actual behavior:** [What actually happened]
**Environment details:** [OS, .NET Runtime, ...]
### Possible Solution
[Optionally, share your idea to fix the issue]

13
.github/ISSUE_TEMPLATE/features.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
## New Feature Proposal
### Description
[Description of the proposed feature]
### Background
Provide any additional background for the feature. e.g., user scenarios.
### Specification
In case of updates that adhere to specification changes, please reference the used specification.

24
.github/PULL_REQUEST_TEMPLATE.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,24 @@
## Types of Changes
### Prerequisites
Please make sure you can check the following two boxes:
- [ ] I have read the **CONTRIBUTING** document
- [ ] My code follows the code style of this project
### Contribution Type
What types of changes does your code introduce? Put an `x` in all the boxes that apply:
- [ ] Bug fix (non-breaking change which fixes an issue, please reference the issue id)
- [ ] New feature (non-breaking change which adds functionality, make sure to open an associated issue first)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] My change requires a change to the documentation
- [ ] I have updated the documentation accordingly
- [ ] I have added tests to cover my changes
- [ ] All new and existing tests passed
### Description
[Place a meaningful description here.]

194
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,194 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
################
## Rider
################
.idea/
################
## VS Code
################
.vscode/
#################
## Visual Studio
#################
## 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/
[Rr]elease/
[Bb]in/
[Bb]uild/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# DNX
*.lock.json
artifacts/
[Dd]ebug/
[Rr]elease/
[Pp]ackages/
[Tt]ools/
![Tt]ools/packages.config
TestResults/
*.nuget.targets
*.nuget.props
*.nupkg
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
*.dotCover
*.dotSettings
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
# ReSharper is a .NET coding add-in
_ReSharper*
# 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
# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# 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
############
## Windows
############
# Windows image file caches
Thumbs.db
# Folder config file
Desktop.ini
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist
build
eggs
parts
var
sdist
develop-eggs
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
# Mac crap
.DS_Store

5
CHANGELOG.md Normal file
Просмотреть файл

@ -0,0 +1,5 @@
# 0.11.0
Planned for Friday, February 1 2019.
- Initial release

11
CONTRIBUTORS.md Normal file
Просмотреть файл

@ -0,0 +1,11 @@
# AngleSharp.Xml Contributors
Thanks :heart: to all who contributed to AngleSharp.Xml via issues, pull requests, suggestions, and questions.
AngleSharp.Xml contains code written by (in order of first pull request / commit):
* [Florian Rappl](https://github.com/FlorianRappl)
Without these awesome people AngleSharp.Xml could not exist. Thanks to everyone for your contributions! :beers:
Missing you? Please contact us! Potentially, the simplest way is to file a PR with your name / GitHub profile link added to this file.

22
LICENSE Normal file
Просмотреть файл

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2019 AngleSharp
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.

52
README.md Normal file
Просмотреть файл

@ -0,0 +1,52 @@
![logo](https://raw.githubusercontent.com/AngleSharp/AngleSharp.Xml/master/header.png)
# AngleSharp.Xml
[![Build Status](https://img.shields.io/appveyor/ci/FlorianRappl/AngleSharp-Xml.svg?style=flat-square)](https://ci.appveyor.com/project/FlorianRappl/AngleSharp-Xml)
[![GitHub Tag](https://img.shields.io/github/tag/AngleSharp/AngleSharp.Xml.svg?style=flat-square)](https://github.com/AngleSharp/AngleSharp.Xml/releases)
[![NuGet Count](https://img.shields.io/nuget/dt/AngleSharp.Xml.svg?style=flat-square)](https://www.nuget.org/packages/AngleSharp.Xml/)
[![Issues Open](https://img.shields.io/github/issues/AngleSharp/AngleSharp.Xml.svg?style=flat-square)](https://github.com/AngleSharp/AngleSharp.Xml/issues)
[![StackOverflow Questions](https://img.shields.io/stackexchange/stackoverflow/t/anglesharp.svg?style=flat-square)](https://stackoverflow.com/tags/anglesharp)
[![CLA Assistant](https://cla-assistant.io/readme/badge/AngleSharp/AngleSharp.Xml?style=flat-square)](https://cla-assistant.io/AngleSharp/AngleSharp.Xml)
AngleSharp.Xml extends the core AngleSharp library with some XML capabilities. This repository is the home of the source for the AngleSharp.Xml NuGet package.
## Basic Configuration
If you just want a configuration *that works* you should use the following code:
```cs
var config = Configuration.Default
.WithXml(); // from AngleSharp.Xml
```
This will register a parser for XML related content.
## Advantages of AngleSharp.Xml over System.Xml
(tbd)
## Features
- Fully compliant XML parser
- XML DOM similar to HTML(5)
- DTD parser and validation check
- XML serialization
## Participating
Participation in the project is highly welcome. For this project the same rules as for the AngleSharp core project may be applied.
If you have any question, concern, or spot an issue then please report it before opening a pull request. An initial discussion is appreciated regardless of the nature of the problem.
## License
The MIT License (MIT)
Copyright (c) 2019 AngleSharp
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.

219
build.cake Normal file
Просмотреть файл

@ -0,0 +1,219 @@
/* ****************************************
Publishing workflow
-------------------
- Update CHANGELOG.md
- Run a normal build with Cake
- Push to devel and FF merge to master
- Switch to master
- Run a Publish build with Cake
- Switch back to devel branch
**************************************** */
#addin "Cake.FileHelpers"
#addin "Octokit"
using Octokit;
var target = Argument("target", "Default");
var configuration = Argument("configuration", "Release");
var isLocal = BuildSystem.IsLocalBuild;
var isRunningOnUnix = IsRunningOnUnix();
var isRunningOnWindows = IsRunningOnWindows();
var isRunningOnAppVeyor = AppVeyor.IsRunningOnAppVeyor;
var isPullRequest = AppVeyor.Environment.PullRequest.IsPullRequest;
var buildNumber = AppVeyor.Environment.Build.Number;
var releaseNotes = ParseReleaseNotes("./CHANGELOG.md");
var version = releaseNotes.Version.ToString();
var buildDir = Directory("./src/AngleSharp.Xml/bin") + Directory(configuration);
var buildResultDir = Directory("./bin") + Directory(version);
var nugetRoot = buildResultDir + Directory("nuget");
// Initialization
// ----------------------------------------
Setup(_ =>
{
Information("Building version {0} of AngleSharp.Xml.", version);
Information("For the publish target the following environment variables need to be set:");
Information(" NUGET_API_KEY, GITHUB_API_TOKEN");
});
// Tasks
// ----------------------------------------
Task("Clean")
.Does(() =>
{
CleanDirectories(new DirectoryPath[] { buildDir, buildResultDir, nugetRoot });
});
Task("Restore-Packages")
.IsDependentOn("Clean")
.Does(() =>
{
NuGetRestore("./src/AngleSharp.Xml.sln", new NuGetRestoreSettings {
ToolPath = "tools/nuget.exe"
});
});
Task("Build")
.IsDependentOn("Restore-Packages")
.Does(() =>
{
DotNetCoreBuild("./src/AngleSharp.Xml.sln", new DotNetCoreBuildSettings() {
Configuration = configuration
});
});
Task("Run-Unit-Tests")
.IsDependentOn("Build")
.Does(() =>
{
var settings = new DotNetCoreTestSettings
{
Configuration = configuration
};
if (isRunningOnAppVeyor)
{
settings.TestAdapterPath = Directory(".");
settings.Logger = "Appveyor";
// TODO Finds a way to exclude tests not allowed to run on appveyor
// Not used in current code
//settings.Where = "cat != ExcludeFromAppVeyor";
}
DotNetCoreTest("./src/AngleSharp.Xml.Tests/", settings);
});
Task("Copy-Files")
.IsDependentOn("Build")
.Does(() =>
{
var mapping = new Dictionary<String, String>
{
{ "net46", "net46" },
{ "netstandard2.0", "netstandard2.0" }
};
if (!isRunningOnWindows)
{
mapping.Remove("net46");
}
foreach (var item in mapping)
{
var targetDir = nugetRoot + Directory("lib") + Directory(item.Key);
CreateDirectory(targetDir);
CopyFiles(new FilePath[]
{
buildDir + Directory(item.Value) + File("AngleSharp.Xml.dll"),
buildDir + Directory(item.Value) + File("AngleSharp.Xml.xml")
}, targetDir);
}
CopyFiles(new FilePath[] { "src/AngleSharp.Xml.nuspec" }, nugetRoot);
});
Task("Create-Package")
.IsDependentOn("Copy-Files")
.Does(() =>
{
var nugetExe = GetFiles("./tools/**/nuget.exe").FirstOrDefault()
?? (isRunningOnAppVeyor ? GetFiles("C:\\Tools\\NuGet3\\nuget.exe").FirstOrDefault() : null);
if (nugetExe == null)
{
throw new InvalidOperationException("Could not find nuget.exe.");
}
var nuspec = nugetRoot + File("AngleSharp.Xml.nuspec");
NuGetPack(nuspec, new NuGetPackSettings
{
Version = version,
OutputDirectory = nugetRoot,
Symbols = false,
Properties = new Dictionary<String, String> { { "Configuration", configuration } }
});
});
Task("Publish-Package")
.IsDependentOn("Create-Package")
.WithCriteria(() => isLocal)
.Does(() =>
{
var apiKey = EnvironmentVariable("NUGET_API_KEY");
if (String.IsNullOrEmpty(apiKey))
{
throw new InvalidOperationException("Could not resolve the NuGet API key.");
}
foreach (var nupkg in GetFiles(nugetRoot.Path.FullPath + "/*.nupkg"))
{
NuGetPush(nupkg, new NuGetPushSettings
{
Source = "https://nuget.org/api/v2/package",
ApiKey = apiKey
});
}
});
Task("Publish-Release")
.IsDependentOn("Publish-Package")
.WithCriteria(() => isLocal)
.Does(() =>
{
var githubToken = EnvironmentVariable("GITHUB_API_TOKEN");
if (String.IsNullOrEmpty(githubToken))
{
throw new InvalidOperationException("Could not resolve AngleSharp GitHub token.");
}
var github = new GitHubClient(new ProductHeaderValue("AngleSharpCakeBuild"))
{
Credentials = new Credentials(githubToken)
};
var newRelease = github.Repository.Release;
newRelease.Create("AngleSharp", "AngleSharp.Xml", new NewRelease("v" + version)
{
Name = version,
Body = String.Join(Environment.NewLine, releaseNotes.Notes),
Prerelease = false,
TargetCommitish = "master"
}).Wait();
});
Task("Update-AppVeyor-Build-Number")
.WithCriteria(() => isRunningOnAppVeyor)
.Does(() =>
{
var num = AppVeyor.Environment.Build.Number;
AppVeyor.UpdateBuildVersion($"{version}-{num}");
});
// Targets
// ----------------------------------------
Task("Package")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Create-Package");
Task("Default")
.IsDependentOn("Package");
Task("Publish")
.IsDependentOn("Publish-Package")
.IsDependentOn("Publish-Release");
Task("AppVeyor")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Update-AppVeyor-Build-Number");
// Execution
// ----------------------------------------
RunTarget(target);

81
build.ps1 Normal file
Просмотреть файл

@ -0,0 +1,81 @@
Param(
[string]$Script = "build.cake",
[string]$Target = "Default",
[ValidateSet("Release", "Debug")]
[string]$Configuration = "Release",
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
[string]$Verbosity = "Verbose",
[switch]$Experimental,
[switch]$WhatIf,
[switch]$Mono,
[switch]$SkipToolPackageRestore,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$ScriptArgs
)
$PSScriptRoot = split-path -parent $MyInvocation.MyCommand.Definition;
$UseDryRun = "";
$UseMono = "";
$TOOLS_DIR = Join-Path $PSScriptRoot "tools"
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
$NUGET_OLD_EXE = Join-Path $TOOLS_DIR "nuget_old.exe"
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
$NUGET_OLD_URL = "https://dist.nuget.org/win-x86-commandline/v3.5.0/nuget.exe"
# Should we use experimental build of Roslyn?
$UseExperimental = "";
if ($Experimental.IsPresent) {
$UseExperimental = "-experimental"
}
# Is this a dry run?
if ($WhatIf.IsPresent) {
$UseDryRun = "-dryrun"
}
# Should we use mono?
if ($Mono.IsPresent) {
$UseMono = "-mono"
}
# Try download NuGet.exe if do not exist.
if (!(Test-Path $NUGET_EXE)) {
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
}
# Try download NuGet.exe if do not exist.
if (!(Test-Path $NUGET_OLD_URL)) {
(New-Object System.Net.WebClient).DownloadFile($NUGET_OLD_URL, $NUGET_OLD_EXE)
}
# Make sure NuGet (latest) exists where we expect it.
if (!(Test-Path $NUGET_EXE)) {
Throw "Could not find nuget.exe"
}
# Make sure NuGet (v3.5.0) exists where we expect it.
if (!(Test-Path $NUGET_OLD_EXE)) {
Throw "Could not find nuget_old.exe"
}
# Restore tools from NuGet?
if (-Not $SkipToolPackageRestore.IsPresent)
{
Push-Location
Set-Location $TOOLS_DIR
Invoke-Expression "$NUGET_EXE install -ExcludeVersion"
Pop-Location
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
# Make sure that Cake has been installed.
if (!(Test-Path $CAKE_EXE)) {
Throw "Could not find Cake.exe"
}
# Start Cake
Invoke-Expression "$CAKE_EXE `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
exit $LASTEXITCODE

93
build.sh Normal file
Просмотреть файл

@ -0,0 +1,93 @@
#!/usr/bin/env bash
###############################################################
# This is the Cake bootstrapper script that is responsible for
# downloading Cake and all specified tools from NuGet.
###############################################################
# Define directories.
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
TOOLS_DIR=$SCRIPT_DIR/tools
NUGET_EXE=$TOOLS_DIR/nuget.exe
NUGET_OLD_EXE=$TOOLS_DIR/nuget_old.exe
CAKE_EXE=$TOOLS_DIR/Cake/Cake.exe
# Define default arguments.
SCRIPT="build.cake"
TARGET="Default"
CONFIGURATION="Release"
VERBOSITY="verbose"
DRYRUN=
SHOW_VERSION=false
SCRIPT_ARGUMENTS=()
# Parse arguments.
for i in "$@"; do
case $1 in
-s|--script) SCRIPT="$2"; shift ;;
-t|--target) TARGET="$2"; shift ;;
-c|--configuration) CONFIGURATION="$2"; shift ;;
-v|--verbosity) VERBOSITY="$2"; shift ;;
-d|--dryrun) DRYRUN="-dryrun" ;;
--version) SHOW_VERSION=true ;;
--) shift; SCRIPT_ARGUMENTS+=("$@"); break ;;
*) SCRIPT_ARGUMENTS+=("$1") ;;
esac
shift
done
# Make sure the tools folder exist.
if [ ! -d $TOOLS_DIR ]; then
mkdir $TOOLS_DIR
fi
# Make sure that packages.config exist.
if [ ! -f $TOOLS_DIR/packages.config ]; then
echo "Downloading packages.config..."
curl -Lsfo $TOOLS_DIR/packages.config http://cakebuild.net/bootstrapper/packages
if [ $? -ne 0 ]; then
echo "An error occured while downloading packages.config."
exit 1
fi
fi
# Download NuGet (v3.5.0) if it does not exist.
if [ ! -f $NUGET_OLD_EXE ]; then
echo "Downloading NuGet..."
curl -Lsfo $NUGET_OLD_EXE https://dist.nuget.org/win-x86-commandline/v3.5.0/nuget.exe
if [ $? -ne 0 ]; then
echo "An error occured while downloading nuget.exe."
exit 1
fi
fi
# Download NuGet (latest) if it does not exist.
if [ ! -f $NUGET_EXE ]; then
echo "Downloading NuGet..."
curl -Lsfo $NUGET_EXE https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
if [ $? -ne 0 ]; then
echo "An error occured while downloading nuget.exe."
exit 1
fi
fi
# Restore tools from NuGet.
pushd $TOOLS_DIR >/dev/null
mono $NUGET_EXE install -ExcludeVersion
if [ $? -ne 0 ]; then
echo "Could not restore NuGet packages."
exit 1
fi
popd >/dev/null
# Make sure that Cake has been installed.
if [ ! -f $CAKE_EXE ]; then
echo "Could not find Cake.exe at '$CAKE_EXE'."
exit 1
fi
# Start Cake
if $SHOW_VERSION; then
exec mono $CAKE_EXE -version
else
exec mono $CAKE_EXE $SCRIPT -verbosity=$VERBOSITY -configuration=$CONFIGURATION -target=$TARGET $DRYRUN "${SCRIPT_ARGUMENTS[@]}"
fi

Двоичные данные
header.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 12 KiB

Двоичные данные
logo.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.5 KiB

Просмотреть файл

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AngleSharp.Xml\AngleSharp.Xml.csproj">
<TargetFramework>netstandard2.0</TargetFramework>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="NUnit" Version="3.11.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.11.0" />
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,43 @@
using AngleSharp.DTD;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
namespace UnitTests
{
/// <summary>
/// Some examples taken from
/// http://xmlwriter.net/xml_guide/doctype_declaration.shtml.
/// </summary>
[TestClass]
public class DTDTree
{
[TestMethod]
public void SubjectsDtd()
{
var dtd = @"<!--see Element Type Declarations
for an explanation of the following syntax-->
<!ELEMENT document
(title*,subjectID,subjectname,prerequisite?,
classes,assessment,syllabus,textbooks*)>
<!ELEMENT prerequisite (subjectID,subjectname)>
<!ELEMENT textbooks (author,booktitle)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT subjectID (#PCDATA)>
<!ELEMENT subjectname (#PCDATA)>
<!ELEMENT classes (#PCDATA)>
<!ELEMENT assessment (#PCDATA)>
<!ATTLIST assessment assessment_type (exam | assignment) #IMPLIED>
<!ELEMENT syllabus (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT booktitle (#PCDATA)>";
var parser = new DtdParser(dtd);
parser.Parse();
var result = parser.Result;
Assert.AreEqual(12, result.Count);
Assert.AreEqual(1, result.Attributes.Count());
Assert.AreEqual(11, result.Elements.Count());
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,74 @@
namespace AngleSharp.Core.Tests.Xml
{
using AngleSharp.Xml.Parser;
using NUnit.Framework;
[TestFixture]
public class XmlTree
{
[Test]
public void XmlValidDocumentWithoutDocType()
{
var xml = (@"<?xml version=""1.0"" encoding=""ISO-8859-1""?>
<!-- Edited by XMLSpy® -->
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>").ToXmlDocument();
Assert.IsNotNull(xml);
Assert.IsNotNull(xml.DocumentElement);
Assert.AreEqual("note", xml.DocumentElement.TagName);
Assert.AreEqual(4, xml.DocumentElement.ChildElementCount);
Assert.AreEqual(4, xml.DocumentElement.Children.Length);
Assert.AreEqual("to", xml.DocumentElement.Children[0].TagName);
Assert.AreEqual("from", xml.DocumentElement.Children[1].TagName);
Assert.AreEqual("heading", xml.DocumentElement.Children[2].TagName);
Assert.AreEqual("body", xml.DocumentElement.Children[3].TagName);
}
[Test]
public void XmlInvalidDocumentMismatchedEndTag()
{
Assert.Catch<XmlParseException>(() => (@"<?xml version=""1.0"" encoding=""ISO-8859-1""?>
<!-- Edited by XMLSpy® -->
<note>
<to>Tove</to>
<from>Jani</Ffrom>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>").ToXmlDocument());
}
[Test]
public void XmlValidDocumentFoodMenuInnerHTML()
{
var xml = Assets.food.ToXmlDocument();
Assert.IsNotNull(xml);
Assert.IsNotNull(xml.DocumentElement);
Assert.AreEqual("breakfast_menu", xml.DocumentElement.TagName);
Assert.AreEqual(5, xml.DocumentElement.ChildElementCount);
Assert.AreEqual(5, xml.DocumentElement.Children.Length);
Assert.AreEqual("food", xml.DocumentElement.Children[0].TagName);
Assert.AreEqual(4, xml.DocumentElement.Children[0].Children.Length);
Assert.AreEqual("name", xml.DocumentElement.Children[0].Children[0].TagName);
Assert.AreEqual("$5.95", xml.DocumentElement.Children[0].Children[1].InnerHtml);
Assert.AreEqual("$7.95", xml.DocumentElement.Children[1].Children[1].InnerHtml);
}
[Test]
public void XmlValidDocumentBooksTree()
{
var xml = Assets.books.ToXmlDocument();
Assert.IsNotNull(xml);
Assert.IsNotNull(xml.DocumentElement);
Assert.AreEqual("catalog", xml.DocumentElement.TagName);
Assert.AreEqual(12, xml.DocumentElement.ChildElementCount);
Assert.AreEqual(6, xml.DocumentElement.Children[2].ChildElementCount);
}
}
}

Двоичные данные
src/AngleSharp.Xml.Tests/Key.snk Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,545 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AngleSharp;
namespace UnitTests
{
[TestClass]
public class XmlInvalidDocuments
{
/// <summary>
/// Tests the Element Valid VC (clause 4) by including an undeclared child element.
/// Here the section(s) 3 apply. This test is taken from the collection Sun
/// Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidEl01()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root ANY>
]>
<root> <undeclared/> </root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Tests the Element Valid VC (clause 1) by including elements in an EMPTY content
/// model. Here the section(s) 3 apply. This test is taken from the collection Sun
/// Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidEl02()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root EMPTY>
]>
<root><root/></root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Tests the Element Valid VC (clause 3) by including a child element not permitted
/// by a mixed content model. Here the section(s) 3 apply. This test is taken from the
/// collection Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidEl03()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root (#PCDATA|root)*>
<!ELEMENT exception (#PCDATA)>
]>
<root>this is ok <exception>this isn't</exception> </root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Tests the Element Valid VC (clause 1), using one of the predefined internal
/// entities inside an EMPTY content model. Here the section(s) 3 apply. This test
/// is taken from the collection Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidEl06()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root EMPTY>
<!-- in case parsers special-case builtin entities incorrectly -->
]>
<root>&amp;</root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Element Valid in P39. Element a is declared empty
/// in DTD, but has content in the document. There is an output test associated
/// with this input file. Here the section(s) 3 apply. This test is taken from the
/// collection IBM XML Conformance Test Suite - Production 39.
/// </summary>
[TestMethod]
public void XmlIbmInvalidP39Ibm39i01()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (a,b)>
<!ELEMENT a EMPTY>
<!ELEMENT b (#PCDATA|c)* >
<!ELEMENT c ANY>
]>
<!--* EMPTY element a has content *-->
<root><a>should not have content here</a><b>
<c></c>
content of b element
</b></root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Element Valid in P39. root is declared only having element
/// children in DTD, but have text content in the document. There is an output test
/// associated with this input file. Here the section(s) 3 apply. This test is taken
/// from the collection IBM XML Conformance Test Suite - Production 39.
/// </summary>
[TestMethod]
public void XmlIbmInvalidP39Ibm39i02()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (a,b)>
<!ELEMENT a EMPTY>
<!ELEMENT b (#PCDATA|c)* >
<!ELEMENT c ANY>
]>
<!--* root element have text content *-->
<root>
root can't have text content
<a></a><b>
<c></c>
content of b element
</b></root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Element Valid in P39. Illegal elements are inserted in b's
/// content of Mixed type. There is an output test associated with this input file. Here
/// the section(s) 3 apply. This test is taken from the collection IBM XML Conformance Test Suite - Production 39.
/// </summary>
[TestMethod]
public void XmlIbmInvalidP39Ibm39i03()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (a,b)>
<!ELEMENT a EMPTY>
<!ELEMENT b (#PCDATA|c)* >
<!ELEMENT c ANY>
]>
<!--* illgal element in b's Mixed content *-->
<root><a/><b>
<c></c>
content of b element
<a/>
could not have 'a' as 'b's content
</b></root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Element Valid in P39. Element c has undeclared element
/// as its content of ANY type There is an output test associated with this input
/// file. Here the section(s) 3 apply. This test is taken from the collection IBM
/// XML Conformance Test Suite - Production 39.
/// </summary>
[TestMethod]
public void XmlIbmInvalidP39Ibm39i04()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (a,b)>
<!ELEMENT a EMPTY>
<!ELEMENT b (#PCDATA|c)* >
<!ELEMENT c ANY>
<!ELEMENT f EMPTY>
]>
<!--* element c has undeclared element as its ANY content *-->
<root><a/><b>
<c><f/></c>
content of b element
<c>
<d>not declared in dtd</d>
</c>
</b></root>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Attribute Value Type in P41. attr1 for Element
/// b is not declared. There is an output test associated with this input
/// file. Here the section(s) 3.1 apply. This test is taken from the collection
/// IBM XML Conformance Test Suite - Production 41.
/// </summary>
[TestMethod]
public void XmIbmInvalidP41Ibm41i01()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (#PCDATA|b)* >
<!ELEMENT b (#PCDATA) >
<!ATTLIST b attr2 (abc|def) ""abc"">
<!ATTLIST b attr3 CDATA #FIXED ""fixed"">
]>
<root>
<b attr1=""value1"" attr2=""def"" attr3=""fixed"">attr1 not declared</b>
</root>
<!--* testing VC:Attribute Value Type *-->
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Attribute Value Type in P41. attr3 for Element
/// b is given a value that does not match the declaration in the DTD. There
/// is an output test associated with this input file. Here the section(s) 3.1
/// apply. This test is taken from the collection IBM XML Conformance Test
/// Suite - Production 41.
/// </summary>
[TestMethod]
public void XmlIbmInvalidP41Ibm41i02()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (PCDATA|b)* >
<!ELEMENT b (#PCDATA) >
<!ATTLIST b attr1 CDATA #REQUIRED>
<!ATTLIST b attr2 (abc|def) ""abc"">
<!ATTLIST b attr3 CDATA #FIXED ""fixed"">
]>
<root>
<b attr1=""value1"" attr2=""abc"" attr3=""shoudbefixed"">attr3 value not fixed</b>
</root>
<!--* testing P41 VC: AtributeValueType*-->
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Elements content can be empty. Here the section(s) 3.1 [40] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP40pass1()
{
var document = DocumentBuilder.Xml(@"<doc></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace is valid within a Start-tag. Here the section(s) 3.1 [40] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP40pass2()
{
var document = DocumentBuilder.Xml(@"<doc
></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace and Multiple Attributes are valid within a Start-tag. Here
/// the section(s) 3.1 [40] apply. This test is taken from the collection
/// OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP40pass4()
{
var document = DocumentBuilder.Xml(@"<doc att=""val"" att2=""val2""
att3=""val3""
></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Attributes are valid within a Start-tag. Here the section(s) 3.1 [40] [41]
/// apply. This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP40pass3()
{
var document = DocumentBuilder.Xml(@"<doc att=""val""></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Attributes are valid within a Start-tag. Here the section(s) 3.1 [41] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP41pass1()
{
var document = DocumentBuilder.Xml(@"<doc att=""val""></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace is valid within a Start-tags Attribute. Here the section(s)
/// 3.1 [41] apply. This test is taken from the collection OASIS/NIST TESTS,
/// 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP41pass2()
{
var document = DocumentBuilder.Xml(@"<doc att
=
""val""></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Test shows proper syntax for an End-tag. Here the section(s) 3.1 [42] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP42pass1()
{
var document = DocumentBuilder.Xml(@"<doc></doc>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace is valid after name in End-tag. Here the section(s) 3.1 [42] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP42pass2()
{
var document = DocumentBuilder.Xml(@"<doc></doc
>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Valid display of an Empty Element Tag. Here the section(s) 3.1 [44] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP44pass1()
{
var document = DocumentBuilder.Xml(@"<doc/>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Empty Element Tags can contain an Attribute. Here the section(s) 3.1 [44]
/// apply. This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP44pass2()
{
var document = DocumentBuilder.Xml(@"<doc att=""val""/>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace is valid in an Empty Element Tag following the end of
/// the attribute value. Here the section(s) 3.1 [44] apply. This test
/// is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP44pass3()
{
var document = DocumentBuilder.Xml(@"<doc att=""val""
/>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace is valid after the name in an Empty Element Tag. Here the
/// section(s) 3.1 [44] apply. This test is taken from the collection
/// OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP44pass4()
{
var document = DocumentBuilder.Xml(@"<doc
/>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Whitespace and Multiple Attributes are valid in an Empty Element Tag.
/// Here the section(s) 3.1 [44] apply. This test is taken from the collection
/// OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlInvalidOP44pass5()
{
var document = DocumentBuilder.Xml(@"<doc att=""val""
att2=""val2"" att3=""val3""/>");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Tests the Attribute Value Type (declared) VC for the xml:space attribute.
/// Here the section(s) 3.1 2.10 apply. This test is taken from the collection
/// Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidInvRequired01()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root EMPTY>
]>
<root xml:space='preserve'/>
<!-- all attributes must be declared -->
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// PE name immediately followed by ";" Here the section(s) 4.1 [69] apply.
/// This test is taken from the collection Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidDtd03()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE violation [
<!ELEMENT violation (a,a,a,b)>
<!ELEMENT a EMPTY>
<!ELEMENT b EMPTY>
<!-- tests the ""element valid"" constraint for content
which doesn't match the declared content model.
(there can be an infinite number of such tests...)
-->
]>
<violation>
<a/>
<a/>
<b/>
</violation>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Tests the Attribute Value Type (declared) VC for the xml:lang attribute.
/// Here the section(s) 3.1 2.12 apply. This test is taken from the collection
/// Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidInvRequired02()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root EMPTY>
]>
<root xml:lang='en'/>
<!-- all attributes must be declared -->
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// Tests the Unique Element Type Declaration VC. Here the section(s)
/// 3.2 apply. This test is taken from the collection Sun Microsystems
/// XML Tests.
/// </summary>
[TestMethod]
public void XmlInvalidEl04()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root ANY>
<!ELEMENT exception (#PCDATA)>
<!ELEMENT exception (#PCDATA)>
]>
<root/>
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
/// <summary>
/// This test violates VC: Unique Element Type Declaration. Element not_unique
/// has been declared 3 time in the DTD. There is an output test associated with
/// this input file. Here the section(s) 3.2 apply. This test is taken from the
/// collection IBM XML Conformance Test Suite - Production 45.
/// </summary>
[TestMethod]
public void XmlIbmInvalidP45Ibm45i01()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE root [
<!ELEMENT root (#PCDATA|b)* >
<!ELEMENT b EMPTY>
<!ELEMENT not_unique ANY>
<!ELEMENT not_unique EMPTY>
<!ELEMENT not_unique (b,b) >
<!ELEMENT unique. ANY>
<!ATTLIST b attr1 CDATA #IMPLIED>
<!ATTLIST b attr2 CDATA #IMPLIED>
<!ATTLIST b attr3 CDATA #IMPLIED>
]>
<root>
<b/>without white space
<b /> with a white space
<b attr1=""value1"" />
<b attr1=""value1"" attr2=""value2"" attr3 = ""value3""/>
</root>
<!--* a invalid test: testing P45 VC unique element type decl *-->
");
Assert.IsNotNull(document);
Assert.IsFalse(document.IsValid);
}
}
}

Просмотреть файл

@ -0,0 +1,80 @@
namespace AngleSharp.Core.Tests.Xml
{
using NUnit.Framework;
using System.Threading.Tasks;
[TestFixture]
public class XmlNamespaceTests
{
[Test]
public async Task XmlWithoutNamespaceUriShouldBeStandardNamespaceUri()
{
var document = await BrowsingContext.New().OpenAsync(req =>
req.Content(@"<a t='42'><b/><c>TEXT</c></a>")
.Header("Content-Type", "text/xml"));
var root = document.DocumentElement;
Assert.AreEqual(null, root.NamespaceUri);
}
[Test]
public async Task XmlWithNewNamespaceShouldContainRightNamespaceUri()
{
var document = await BrowsingContext.New().OpenAsync(req =>
req.Content(@"<a xmlns=""http://www.w3.org/1999/xhtml"" t=""42""><b/><c>TEXT</c></a>")
.Header("Content-Type", "text/xml"));
var root = document.DocumentElement;
Assert.AreEqual("http://www.w3.org/1999/xhtml", root.NamespaceUri);
}
[Test]
public async Task XmlWithCustomNamespaceShouldExposeThatNamespaceUri()
{
var document = await BrowsingContext.New().OpenAsync(req =>
req.Content(@"<x:a xmlns:x=""http://initd.org/ns/tesseract-1.0"" t=""42""><b/><c>TEXT</c></x:a>")
.Header("Content-Type", "text/xml"));
var root = document.DocumentElement;
Assert.AreEqual("http://initd.org/ns/tesseract-1.0", root.NamespaceUri);
}
[Test]
public async Task XmlSubElementsGetTheRightDefaultNamespace()
{
var document = await BrowsingContext.New().OpenAsync(req =>
req.Content(@"<xml xmlns=""http://test.com""><child attr=""1""/></xml>")
.Header("Content-Type", "text/xml"));
var root = document.DocumentElement;
Assert.AreEqual("http://test.com", root.NamespaceUri);
Assert.AreEqual("http://test.com", root.LookupNamespaceUri(""));
Assert.AreEqual("http://test.com", root.FirstElementChild.NamespaceUri);
Assert.AreEqual("http://test.com", root.FirstElementChild.LookupNamespaceUri(""));
Assert.AreEqual(null, root.FirstElementChild.Attributes["attr"].NamespaceUri);
}
[Test]
public async Task XmlPrefixRefersToDefinedNamespace()
{
var document = await BrowsingContext.New().OpenAsync(req =>
req.Content(@"<xml xmlns:p1=""http://p1.com"" xmlns:p2=""http://p2.com""><p1:child a=""1"" p1:attr=""1"" b=""2""/><p2:child/></xml>")
.Header("Content-Type", "text/xml"));
var root = document.DocumentElement;
Assert.AreEqual("http://p1.com", root.FirstElementChild.NamespaceUri);
Assert.AreEqual("http://p1.com", root.LookupNamespaceUri("p1"));
Assert.AreEqual(null, root.FirstElementChild.GetAttribute("attr"));
Assert.AreEqual("http://p1.com", root.FirstElementChild.Attributes["p1:attr"].NamespaceUri);
Assert.AreEqual("http://p2.com", root.FirstElementChild.NextElementSibling.NamespaceUri);
Assert.AreEqual("http://p2.com", root.FirstElementChild.NextElementSibling.LookupNamespaceUri("p2"));
}
[Test]
public async Task XmlRedefinitionOfPrefixedNamespace()
{
var document = await BrowsingContext.New().OpenAsync(req =>
req.Content(@"<xml xmlns:p=""http://test.com""><p:child xmlns:p=""http://p.com""/><p:child/></xml>")
.Header("Content-Type", "text/xml"));
var root = document.DocumentElement;
Assert.AreEqual("http://p.com", root.FirstElementChild.NamespaceUri);
Assert.AreEqual("http://test.com", root.LastElementChild.NamespaceUri);
Assert.AreEqual("http://test.com", root.FirstElementChild.NextElementSibling.LookupNamespaceUri("p"));
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,163 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AngleSharp;
using AngleSharp.Xml;
namespace UnitTests
{
[TestClass]
public class XmlNotWfExtDtd
{
[TestInitialize]
public void SetUp()
{
Configuration.RegisterHttpRequester<DtdRequester>();
}
[TestCleanup]
public void CleanUp()
{
Configuration.UnregisterHttpRequester<DtdRequester>();
}
/// <summary>
/// Text declarations (which optionally begin any external entity) are
/// required to have "encoding=...". Here the section(s) 4.3.1 [77] apply.
/// This test is taken from the collection Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfDtd07()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root SYSTEM ""dtd07.dtd"" [
<!ELEMENT root EMPTY>
]>
<root/>
");
}
/// <summary>
/// Text declarations (which optionally begin any external entity) are required
/// to have "encoding=...". Here the section(s) 4.3.1 [77] apply. This test is taken
/// from the collection Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfEncoding07()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root [
<!ELEMENT root EMPTY>
<!--
reusing this entity; it's got no markup decls,
so it's legal except for a missing ""encoding=..."".
-->
<!ENTITY empty SYSTEM ""dtd07.dtd"">
]>
<root>&empty;</root>
");
}
/// <summary>
/// Only INCLUDE and IGNORE are conditional section keywords. Here the section(s) 3.4 [61] apply.
/// This test is taken from the collection Sun Microsystems XML Tests.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfCond01()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE root SYSTEM ""cond.dtd"" [
<!ENTITY % MAYBE ""CDATA"">
]>
<root/>
");
}
/// <summary>
/// no other types, including TEMP, which is valid in SGML Here the section(s) 3.4 [61] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP61fail1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p61fail1.dtd"">
<doc/>");
}
/// <summary>
/// INCLUDE must be upper case Here the section(s) 3.4 [62] apply. This
/// test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP62fail1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p62fail1.dtd"">
<doc/>");
}
/// <summary>
/// no spaces in terminating delimiter Here the section(s) 3.4 [62] apply. This test
/// is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP62fail2()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p62fail2.dtd"">
<doc/>");
}
/// <summary>
/// IGNORE must be upper case Here the section(s) 3.4 [63] apply. This test is taken
/// from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP63fail1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p63fail1.dtd"">
<doc/>");
}
/// <summary>
/// delimiters must be balanced Here the section(s) 3.4 [63] apply. This test is taken
/// from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP63fail2()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p63fail2.dtd"">
<doc/>");
}
/// <summary>
/// section delimiters must balance Here the section(s) 3.4 [64] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP64fail1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p64fail1.dtd"">
<doc/>
");
}
/// <summary>
/// section delimiters must balance Here the section(s) 3.4 [64] apply.
/// This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
[ExpectedException(typeof(XmlSyntaxException))]
public void XmlNotWfOP64fail2()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p64fail2.dtd"">
<doc/>
");
}
}
}

Просмотреть файл

@ -0,0 +1,75 @@
namespace AngleSharp.Core.Tests.Xml
{
using AngleSharp.Xml.Parser;
using NUnit.Framework;
[TestFixture]
public class XmlParsing
{
[Test]
public void ParseHtmlStructureInXmlShouldThrowError()
{
var source = @" <title>My Title</title>
<p>My paragraph</p>";
var parser = new XmlParser();
Assert.Catch<XmlParseException>(() => parser.ParseDocument(source));
}
[Test]
public void ParseHtmlStructureInXmlShouldNotThrowErrorIfSuppressed()
{
var source = @" <title>My Title</title>
<p>My paragraph</p>";
var parser = new XmlParser(new XmlParserOptions
{
IsSuppressingErrors = true
});
var document = parser.ParseDocument(source);
Assert.AreEqual(1, document.Children.Length);
}
[Test]
public void ParseHtmlEntityInXmlShouldThrowError()
{
var source = @" <title>&nbsp;</title>";
var parser = new XmlParser();
Assert.Catch<XmlParseException>(() => parser.ParseDocument(source));
}
[Test]
public void ParseHtmlEntityInXmlShouldNotThrowErrorIfSuppressed()
{
var source = @" <title>&nbsp;</title>";
var parser = new XmlParser(new XmlParserOptions
{
IsSuppressingErrors = true
});
var document = parser.ParseDocument(source);
Assert.AreEqual(1, document.Children.Length);
}
[Test]
public void ParseValidXmlEntityShouldBeRepresentedCorrectly()
{
var source = @" <title>&amp;</title>";
var parser = new XmlParser(new XmlParserOptions
{
IsSuppressingErrors = true
});
var document = parser.ParseDocument(source);
Assert.AreEqual("&", document.DocumentElement.TextContent);
}
[Test]
public void ParseInvalidXmlEntityShouldBeSerialized()
{
var source = @" <title>&nbsp;</title>";
var parser = new XmlParser(new XmlParserOptions
{
IsSuppressingErrors = true
});
var document = parser.ParseDocument(source);
Assert.AreEqual("&nbsp;", document.DocumentElement.TextContent);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,455 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AngleSharp;
namespace UnitTests
{
[TestClass]
public class XmlValidExtDtd
{
[TestInitialize]
public void SetUp()
{
Configuration.RegisterHttpRequester<DtdRequester>();
}
[TestCleanup]
public void CleanUp()
{
Configuration.UnregisterHttpRequester<DtdRequester>();
}
/// <summary>
/// Tests EnitityValue referencing a Parameter Entity. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test
/// is taken from the collection IBM XML Conformance Test Suite - Production 9.
/// </summary>
[TestMethod]
public void XmlIbmValidP09Ibm09v03()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student SYSTEM ""ibm09v03.dtd"">
<student>I am a new student with &Name;</student>
");
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Testing PubidChar with all legal PubidChar in a PubidLiteral. There is an
/// output test associated with this input file. Here the section(s) 2.3 apply.
/// This test is taken from the collection IBM XML Conformance Test Suite -
/// Production 13.
/// </summary>
[TestMethod]
public void XmlIbmValidP13Ibm13v01()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student PUBLIC ""#x20 #xD #xA abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -'()+,./:=?;!*#@$_% "" ""student.dtd"">
<!-- testing Pubid char with all legal pubidchar in a string -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests regular systemliteral using the double quotes. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test is
/// taken from the collection IBM XML Conformance Test Suite - Production 12.
/// </summary>
[TestMethod]
public void XmlIbmValidP12Ibm12v03()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student PUBLIC ""The big ' in it"" ""student.dtd"">
<!-- testing Pubid Literal with a string with ""'"" inside -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// valid EntityValue's. Except for entity references, markup is not recognized.
/// Here the section(s) 2.3 [9] apply. This test is taken from the collection
/// OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP09pass1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p09pass1.dtd"">
<doc/>", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Constructs an &lt;!ATTLIST...&gt; declaration from several PEs. There is an output test
/// associated with this input file. Here the section(s) 2.8, 4.1 [69] apply. This test
/// is taken from the collection James Clark XMLTEST cases, 18-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidNotSa024()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""023.ent"">
<doc></doc>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
Assert.IsNotNull(document.DocumentElement);
Assert.IsNotNull(document.DocumentElement.Attributes["a1"]);
Assert.AreEqual("v1", document.DocumentElement.Attributes["a1"].Value);
}
/// <summary>
/// Test demonstrates the use of a parameter entity reference within an attribute
/// list declaration. There is an output test associated with this input file. Here
/// the section(s) 2.3 4.1 [10] [69] apply. This test is taken from the collection
/// James Clark XMLTEST cases, 18-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidNotSa023()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""023.ent"">
<doc></doc>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
Assert.IsNotNull(document.DocumentElement);
Assert.IsNotNull(document.DocumentElement.Attributes["a1"]);
Assert.AreEqual("v1", document.DocumentElement.Attributes["a1"].Value);
}
/// <summary>
/// Tests doctypedecl with external subset and combinations of different markup declarations
/// and PEReferences. There is an output test associated with this input file. Here the section(s)
/// 2.8 apply. This test is taken from the collection IBM XML Conformance Test Suite - Production 28.
/// </summary>
[TestMethod]
public void XmlIbmValidP28Ibm28v02()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0"" encoding=""utf-8"" ?>
<!DOCTYPE animal SYSTEM ""ibm28v02.dtd"" [
<!NOTATION animal_class SYSTEM ""ibm28v02.txt"">
<!ENTITY forcat ""This is a small cat"">
<!ELEMENT tiger (#PCDATA)>
<!ENTITY % make_small ""<!ELEMENT small EMPTY>"">
<!ENTITY % make_leopard_element ""<!ELEMENT leopard ANY>"">
<!ENTITY % make_attlist ""<!ATTLIST tiger color CDATA #REQUIRED>"">
%make_leopard_element;
<!ELEMENT cat ANY>
%make_small;
<!ENTITY % make_big ""<!ELEMENT big EMPTY>"">
%make_big;
%make_attlist;
<?sound ""This is a PI"" ?>
<!-- This is a valid test file for p28 -->
]>
<animal>
<cat>&forcat;</cat>
<tiger color=""white"">This is a white tiger in Mirage!!</tiger>
<cat/>
<leopard>
<small/>
<big/>
</leopard>
</animal>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests extSubset with TextDecl and extSubsetDecl in the dtd file. There is an output test
/// associated with this input file. Here the section(s) 2.8 apply. This test is taken from
/// the collection IBM XML Conformance Test Suite - Production 30.
/// </summary>
[TestMethod]
public void XmlIbmValidP30Ibm30v02()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE animal SYSTEM ""ibm30v02.dtd"">
<animal/>
<!-- tests extSubset with TextDecl and extSubsetDecl in the dtd file -->
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests EnitityValue with combination of GE, PE and text, the GE used is declared
/// in the student.dtd. There is an output test associated with this input file.
/// Here the section(s) 2.3 apply. This test is taken from the collection IBM XML
/// Conformance Test Suite - Production 9.
/// </summary>
[TestMethod]
public void XmlIbmValidP09Ibm09v05()
{
var fullname = "first , last , middle";
var age = "21";
var status = "freshman";
var combine = String.Format("This is a test of My Name is {0} and my age is {1} Again {0} {0} and my status is \n\t\t{2} {2} and {0} {1} {0} {2} That is all.",
fullname, age, status);
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student SYSTEM ""student2.dtd""[
<!ELEMENT student (#PCDATA)>
<!ENTITY Age ""21"">
<!ENTITY Status ""freshman"">
<!ENTITY % FullName ""first , last , middle"">
]>
<!-- testing entity value with combination reference -->
<student>This is a test of &combine;</student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
Assert.AreEqual(combine, document.DocumentElement.TextContent);
}
/// <summary>
/// Tests regular systemliteral using the single quotes. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test is
/// taken from the collection IBM XML Conformance Test Suite - Production 11.
/// </summary>
[TestMethod]
public void XmlIbmValidP11Ibm11v03()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student SYSTEM 'student.dtd'[
]>
<!-- testing systemliteral with a string with ""'"" -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests regular systemliteral using the double quotes. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test is
/// taken from the collection IBM XML Conformance Test Suite - Production 11.
/// </summary>
[TestMethod]
public void XmlIbmValidP11Ibm11v04()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student SYSTEM ""student.dtd"" [
]>
<!-- testing systemliteral with a string with '""' -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests empty systemliteral using the double quotes. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test is
/// taken from the collection IBM XML Conformance Test Suite - Production 12.
/// </summary>
[TestMethod]
public void XmlIbmValidP12Ibm12v01()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student PUBLIC """" ""student.dtd""[
]>
<!-- testing Pubid Literal with nothing between the double quote -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests empty systemliteral using the single quotes. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test is
/// taken from the collection IBM XML Conformance Test Suite - Production 12.
/// </summary>
[TestMethod]
public void XmlIbmValidP12Ibm12v02()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student PUBLIC '' 'student.dtd'[
]>
<!-- testing Pubid Literal with nothing between the single quotes -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Tests regular systemliteral using the single quotes. There is an output test
/// associated with this input file. Here the section(s) 2.3 apply. This test is
/// taken from the collection IBM XML Conformance Test Suite - Production 12.
/// </summary>
[TestMethod]
public void XmlIbmValidP12Ibm12v04()
{
var document = DocumentBuilder.Xml(@"<?xml version=""1.0""?>
<!DOCTYPE student PUBLIC 'The latest version' 'student.dtd'[
]>
<!-- testing Pubid Literal with a string without ""'"" inside -->
<student>My Name is SnowMan. </student>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Expands a general entity which contains a CDATA section with what looks like a
/// markup declaration (but is just text since it's in a CDATA section). There is an
/// output test associated with this input file. Here the section(s) 2.7 apply. This
/// test is taken from the collection James Clark XMLTEST cases, 18-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidNotSa031()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""031-1.ent"">
<doc>&e;</doc>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// external subset can be empty. Here the section(s) 2.8 [31] apply. This test is taken
/// from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP31pass1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p31pass1.dtd"" [<!ELEMENT doc EMPTY>]>
<doc/>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Valid doctypedecl with EXternalID as Enternal Entity. The external entity contains a parameter
/// entity reference and condtional sections. Here the section(s) 2.8 3.4 4.2.2 [31] [62] [63] [75]
/// apply. This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP31pass2()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p31pass2.dtd"">
<doc/>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Valid doctypedecl with ExternalID as an External Entity. A parameter entity reference is also used.
/// Here the section(s) 2.8 4.1 [28] [69] apply. This test is taken from the collection OASIS/NIST
/// TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP28pass5()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p28pass5.dtd""[
<!--comment-->
<!ENTITY % rootdecl ""<!ELEMENT doc (a)>"">
<!ELEMENT a EMPTY>
]>
<doc><a/></doc>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Valid doctypedecl with ExternalID as an External Entity declaration. Here the section(s) 2.8 4.2.2
/// [28] [75] apply. This test is taken from the collection OASIS/NIST TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP28pass4()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p28pass4.dtd"">
<doc/>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Valid doctypedecl with ExternalID as an External Entity. The external entity has an element declaration.
/// Here the section(s) 2.8 4.2.2 [30] [75] apply. This test is taken from the collection OASIS/NIST TESTS,
/// 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP30pass1()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p30pass1.dtd"">
<doc/>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
/// <summary>
/// Valid doctypedecl with ExternalID as an Enternal Entity. The external entity begins with a Text Declaration.
/// Here the section(s) 2.8 4.2.2 4.3.1 [30] [75] [77] apply. This test is taken from the collection OASIS/NIST
/// TESTS, 1-Nov-1998.
/// </summary>
[TestMethod]
public void XmlValidOP30pass2()
{
var document = DocumentBuilder.Xml(@"<!DOCTYPE doc SYSTEM ""p30pass2.dtd"">
<doc/>
", new DocumentOptions(validating: true));
Assert.IsNotNull(document);
Assert.IsTrue(document.IsValid);
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © AngleSharp, 2013-2019.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

Просмотреть файл

@ -0,0 +1,24 @@
namespace AngleSharp.Xml.Tests
{
using AngleSharp.Dom;
using AngleSharp.Html.Parser;
using AngleSharp.Xml.Parser;
using System;
static class TestExtensions
{
public static IDocument ToXmlDocument(this String sourceCode, IConfiguration configuration = null)
{
var context = BrowsingContext.New(configuration);
var xmlParser = context.GetService<IXmlParser>();
return xmlParser.ParseDocument(sourceCode);
}
public static IDocument ToHtmlDocument(this String sourceCode, IConfiguration configuration = null)
{
var context = BrowsingContext.New(configuration ?? Configuration.Default);
var htmlParser = context.GetService<IHtmlParser>();
return htmlParser.ParseDocument(sourceCode);
}
}
}

Просмотреть файл

@ -0,0 +1,216 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using AngleSharp;
using AngleSharp.Xml;
using AngleSharp.DTD;
namespace UnitTests
{
[TestClass]
public class XmlDTD
{
[TestMethod]
public void TVScheduleDtdSubset()
{
var dtd = @"<!ELEMENT TVSCHEDULE (CHANNEL+)>
<!ELEMENT CHANNEL (BANNER,DAY+)>
<!ELEMENT BANNER (#PCDATA)>
<!ELEMENT DAY (DATE,(HOLIDAY|PROGRAMSLOT+)+)>
<!ELEMENT HOLIDAY (#PCDATA)>
<!ELEMENT DATE (#PCDATA)>
<!ELEMENT PROGRAMSLOT (TIME,TITLE,DESCRIPTION?)>
<!ELEMENT TIME (#PCDATA)>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT DESCRIPTION (#PCDATA)>
<!ATTLIST TVSCHEDULE NAME CDATA #REQUIRED>
<!ATTLIST CHANNEL CHAN CDATA #REQUIRED>
<!ATTLIST PROGRAMSLOT VTR CDATA #IMPLIED>
<!ATTLIST TITLE RATING CDATA #IMPLIED>
<!ATTLIST TITLE LANGUAGE CDATA #IMPLIED>";
var text = "<!DOCTYPE TVSCHEDULE [" + dtd + "]>";
var s = new SourceManager(text);
var t = new XmlTokenizer(s);
t.DTD.Reset();
var e = t.Get();
Assert.AreEqual(XmlTokenType.DOCTYPE, e.Type);
var d = (XmlDoctypeToken)e;
Assert.IsFalse(d.IsNameMissing);
Assert.AreEqual("TVSCHEDULE", d.Name);
Assert.IsTrue(d.IsSystemIdentifierMissing);
Assert.AreEqual(15, t.DTD.Count);
//Unfortunately C# counts newlines with 2 characters since \r\n is used
Assert.AreEqual(dtd.Replace("\r\n", "\n"), d.InternalSubset);
//This is annoying but meh - what can we do? W3C specifies we need to use
//\n for newlines and omit \r completely.
}
[TestMethod]
public void TVScheduleDtdComplete()
{
var dtd = @"<!DOCTYPE TVSCHEDULE [
<!ELEMENT TVSCHEDULE (CHANNEL+)>
<!ELEMENT CHANNEL (BANNER,DAY+)>
<!ELEMENT BANNER (#PCDATA)>
<!ELEMENT DAY (DATE,(HOLIDAY|PROGRAMSLOT+)+)>
<!ELEMENT HOLIDAY (#PCDATA)>
<!ELEMENT DATE (#PCDATA)>
<!ELEMENT PROGRAMSLOT (TIME,TITLE,DESCRIPTION?)>
<!ELEMENT TIME (#PCDATA)>
<!ELEMENT TITLE (#PCDATA)>
<!ELEMENT DESCRIPTION (#PCDATA)>
<!ATTLIST TVSCHEDULE NAME CDATA #REQUIRED>
<!ATTLIST CHANNEL CHAN CDATA #REQUIRED>
<!ATTLIST PROGRAMSLOT VTR CDATA #IMPLIED>
<!ATTLIST TITLE RATING CDATA #IMPLIED>
<!ATTLIST TITLE LANGUAGE CDATA #IMPLIED>
]>";
var s = new SourceManager(dtd);
var t = new XmlTokenizer(s);
t.DTD.Reset();
var e = t.Get();
Assert.IsTrue(t.DTD[0] is ElementDeclaration);
var f1 = (t.DTD[0] as ElementDeclaration);
Assert.AreEqual("TVSCHEDULE", f1.Name);
Assert.AreEqual(ElementContentType.Children, f1.Entry.Type);
Assert.IsTrue(f1.Entry is ElementChoiceDeclarationEntry);
var g1 = (f1.Entry as ElementChoiceDeclarationEntry);
Assert.AreEqual(ElementQuantifier.One, g1.Quantifier);
Assert.AreEqual(1, g1.Choice.Count);
Assert.IsTrue(g1.Choice[0] is ElementNameDeclarationEntry);
var h1 = (g1.Choice[0] as ElementNameDeclarationEntry);
Assert.AreEqual(ElementQuantifier.OneOrMore, h1.Quantifier);
Assert.AreEqual("CHANNEL", h1.Name);
Assert.IsTrue(t.DTD[3] is ElementDeclaration);
var f2 = (t.DTD[3] as ElementDeclaration);
Assert.AreEqual("DAY", f2.Name);
Assert.AreEqual(ElementContentType.Children, f2.Entry.Type);
Assert.IsTrue(f2.Entry is ElementSequenceDeclarationEntry);
var g2 = (f2.Entry as ElementSequenceDeclarationEntry);
Assert.AreEqual(ElementQuantifier.One, g2.Quantifier);
Assert.AreEqual(2, g2.Sequence.Count);
Assert.AreEqual(ElementQuantifier.One, g2.Sequence[0].Quantifier);
Assert.AreEqual(ElementQuantifier.OneOrMore, g2.Sequence[1].Quantifier);
Assert.IsTrue(g2.Sequence[0] is ElementNameDeclarationEntry);
Assert.IsTrue(g2.Sequence[1] is ElementChoiceDeclarationEntry);
var g3 = (g2.Sequence[0] as ElementNameDeclarationEntry);
var g4 = (g2.Sequence[1] as ElementChoiceDeclarationEntry);
Assert.AreEqual("DATE", g3.Name);
Assert.AreEqual(2, g4.Choice.Count);
Assert.IsTrue(g4.Choice[0] is ElementNameDeclarationEntry);
Assert.IsTrue(g4.Choice[1] is ElementNameDeclarationEntry);
var g5 = (g4.Choice[0] as ElementNameDeclarationEntry);
var g6 = (g4.Choice[1] as ElementNameDeclarationEntry);
Assert.AreEqual("HOLIDAY", g5.Name);
Assert.AreEqual("PROGRAMSLOT", g6.Name);
Assert.AreEqual(ElementQuantifier.One, g5.Quantifier);
Assert.AreEqual(ElementQuantifier.OneOrMore, g6.Quantifier);
Assert.IsTrue(t.DTD[10] is AttributeDeclaration);
var f7 = (t.DTD[10] as AttributeDeclaration);
Assert.AreEqual("TVSCHEDULE", f7.Name);
Assert.AreEqual(1, f7.Count);
Assert.AreEqual("NAME", f7[0].Name);
Assert.IsInstanceOfType(f7[0].Type, typeof(AttributeStringType));
Assert.IsInstanceOfType(f7[0].Default, typeof( AttributeRequiredValue));
}
[TestMethod]
public void NewspaperDtdComplete()
{
var s = new SourceManager(@"<!DOCTYPE NEWSPAPER [
<!ELEMENT NEWSPAPER (ARTICLE+)>
<!ELEMENT ARTICLE (HEADLINE,BYLINE,LEAD,BODY,NOTES)>
<!ELEMENT HEADLINE (#PCDATA)>
<!ELEMENT BYLINE (#PCDATA)>
<!ELEMENT LEAD (#PCDATA)>
<!ELEMENT BODY (#PCDATA)>
<!ELEMENT NOTES (#PCDATA)>
<!ATTLIST ARTICLE AUTHOR CDATA #REQUIRED>
<!ATTLIST ARTICLE EDITOR CDATA #IMPLIED>
<!ATTLIST ARTICLE DATE CDATA #IMPLIED>
<!ATTLIST ARTICLE EDITION CDATA #IMPLIED>
<!ENTITY NEWSPAPER ""Vervet Logic Times"">
<!ENTITY PUBLISHER ""Vervet Logic Press"">
<!ENTITY COPYRIGHT 'Copyright 1998 Vervet Logic Press'>
]>");
var t = new XmlTokenizer(s);
t.DTD.Reset();
var e = t.Get();
Assert.AreEqual(XmlTokenType.DOCTYPE, e.Type);
var d = (XmlDoctypeToken)e;
Assert.IsFalse(d.IsNameMissing);
Assert.AreEqual("NEWSPAPER", d.Name);
Assert.IsTrue(d.IsSystemIdentifierMissing);
Assert.AreEqual(14, t.DTD.Count);
}
[TestMethod]
public void ProductCatalogDtdComplete()
{
var s = new SourceManager(@"<!DOCTYPE CATALOG [
<!ENTITY AUTHOR ""John Doe"">
<!ENTITY COMPANY ""JD Power Tools, Inc."">
<!ENTITY EMAIL ""jd@jd-tools.com"">
<!ELEMENT CATALOG (PRODUCT+)>
<!ELEMENT PRODUCT
(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)>
<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) ""HandTool""
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) ""Chicago""
INVENTORY (InStock|Backordered|Discontinued) ""InStock"">
<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>
<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) ""Matte""
ADAPTER (Included|Optional|NotApplicable) ""Included""
CASE (HardShell|Soft|NotApplicable) ""HardShell"">
<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>
<!ELEMENT NOTES (#PCDATA)>
]>");
var t = new XmlTokenizer(s);
t.DTD.Reset();
var e = t.Get();
Assert.AreEqual(XmlTokenType.DOCTYPE, e.Type);
var d = (XmlDoctypeToken)e;
Assert.IsFalse(d.IsNameMissing);
Assert.AreEqual("CATALOG", d.Name);
Assert.IsTrue(d.IsSystemIdentifierMissing);
Assert.AreEqual(13, t.DTD.Count);
}
}
}

Просмотреть файл

@ -0,0 +1,187 @@
namespace AngleSharp.Core.Tests.Xml
{
using AngleSharp.Core.Tests.Mocks;
using AngleSharp.Text;
using AngleSharp.Xml;
using AngleSharp.Xml.Parser;
using AngleSharp.Xml.Parser.Tokens;
using NUnit.Framework;
[TestFixture]
public class XmlTokenization
{
private static XmlTokenizer CreateTokenizer(TextSource source)
{
return new XmlTokenizer(source, XmlEntityProvider.Resolver);
}
[Test]
public void EmptyXmlDocumentTokenization()
{
var s = new TextSource("");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.IsInstanceOf<XmlEndOfFileToken>(e);
}
[Test]
public void OneCommentInXmlDocument()
{
var c = "My comment";
var s = new TextSource("<!--" + c + "-->");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.AreEqual(XmlTokenType.Comment, e.Type);
Assert.AreEqual(c, ((XmlCommentToken)e).Data);
}
[Test]
public void ValidXmlDeclarationOnlyVersion()
{
var s = new TextSource("<?xml version=\"1.0\"?>");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.AreEqual(XmlTokenType.Declaration, e.Type);
Assert.AreEqual("1.0", ((XmlDeclarationToken)e).Version);
}
[Test]
public void ValidXmlDeclarationVersionAndEncoding()
{
var s = new TextSource("<?xml version=\"1.1\" encoding=\"utf-8\" ?>");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.AreEqual(XmlTokenType.Declaration, e.Type);
var x = (XmlDeclarationToken)e;
Assert.AreEqual("1.1", x.Version);
Assert.IsFalse(x.IsEncodingMissing);
Assert.AreEqual("utf-8", x.Encoding);
}
[Test]
public void ValidXmlDeclarationEverything()
{
var s = new TextSource("<?xml version='1.0' encoding='ISO-8859-1' standalone=\"yes\" ?>");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.AreEqual(XmlTokenType.Declaration, e.Type);
var x = (XmlDeclarationToken)e;
Assert.AreEqual("1.0", x.Version);
Assert.IsFalse(x.IsEncodingMissing);
Assert.AreEqual("ISO-8859-1", x.Encoding);
Assert.AreEqual(true, x.Standalone);
}
[Test]
public void OneDoctypeInXmlDocument()
{
var s = new TextSource("<!DOCTYPE root_element SYSTEM \"DTD_location\">");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.AreEqual(XmlTokenType.Doctype, e.Type);
var d = (XmlDoctypeToken)e;
Assert.IsFalse(d.IsNameMissing);
Assert.AreEqual("root_element", d.Name);
Assert.IsFalse(d.IsSystemIdentifierMissing);
Assert.AreEqual("DTD_location", d.SystemIdentifier);
}
[Test]
public void XmlTokenizerStringToken()
{
var s = new TextSource("teststring\r");
var t = CreateTokenizer(s);
var e = t.Get();
Assert.AreEqual(XmlTokenType.Character, e.Type);
var x = (XmlCharacterToken)e;
Assert.AreEqual("teststring\n", x.Data);
}
[Test]
public void XmlTokenizerStringAndStandardEntityToken()
{
var s = new TextSource("test&amp;string\r");
var t = CreateTokenizer(s);
var test = t.Get();
var end = t.Get();
Assert.AreEqual(XmlTokenType.Character, test.Type);
Assert.AreEqual("test&string\n", ((XmlCharacterToken)test).Data);
Assert.AreEqual(XmlTokenType.EndOfFile, end.Type);
}
[Test]
public void XmlTokenizerStringAndCustomEntityToken()
{
var resolver = new MockEntityProvider(str => str.Equals("bar;") ? "foo" : null);
var s = new TextSource("test&bar;");
var t = new XmlTokenizer(s, resolver);
var test = t.Get();
var end = t.Get();
Assert.AreEqual(XmlTokenType.Character, test.Type);
Assert.AreEqual("testfoo", ((XmlCharacterToken)test).Data);
Assert.AreEqual(XmlTokenType.EndOfFile, end.Type);
}
[Test]
public void XmlTokenizerNumericCharacterReferences()
{
var s = new TextSource("test&#97;&#x62;\r");
var t = CreateTokenizer(s);
var test = t.Get();
var end = t.Get();
Assert.AreEqual(XmlTokenType.Character, test.Type);
Assert.AreEqual("testab\n", ((XmlCharacterToken)test).Data);
Assert.AreEqual(XmlTokenType.EndOfFile, end.Type);
}
[Test]
public void XmlTokenizerStringAndTagToken()
{
var s = new TextSource("<foo>test</bar>");
var t = CreateTokenizer(s);
var foo = t.Get();
var test = t.Get();
var bar = t.Get();
var end = t.Get();
Assert.AreEqual(XmlTokenType.StartTag, foo.Type);
Assert.AreEqual(XmlTokenType.EndTag, bar.Type);
Assert.AreEqual("foo", ((XmlTagToken)foo).Name);
Assert.AreEqual("bar", ((XmlTagToken)bar).Name);
Assert.AreEqual("test", ((XmlCharacterToken)test).Data);
Assert.AreEqual(XmlTokenType.EndOfFile, end.Type);
}
[Test]
public void XmlTokenizerSelfClosingTagWithAttribute()
{
var s = new TextSource("<foo bar=\"quz\" />");
var t = CreateTokenizer(s);
var foo = t.Get() as XmlTagToken;
Assert.IsNotNull(foo);
Assert.AreEqual(XmlTokenType.StartTag, foo.Type);
Assert.IsTrue(foo.IsSelfClosing);
Assert.AreEqual("foo", foo.Name);
Assert.AreEqual(1, foo.Attributes.Count);
Assert.AreEqual("bar", foo.Attributes[0].Key);
Assert.AreEqual("quz", foo.Attributes[0].Value);
}
[Test]
public void XmlTokenizerTagWithAttributeContainingEntity()
{
var s = new TextSource("<foo bar=\"&quot;quz&quot;\">");
var t = CreateTokenizer(s);
var foo = t.Get() as XmlTagToken;
Assert.IsNotNull(foo);
Assert.AreEqual(XmlTokenType.StartTag, foo.Type);
Assert.IsFalse(foo.IsSelfClosing);
Assert.AreEqual("foo", foo.Name);
Assert.AreEqual(1, foo.Attributes.Count);
Assert.AreEqual("bar", foo.Attributes[0].Key);
Assert.AreEqual("\"quz\"", foo.Attributes[0].Value);
}
}
}

Просмотреть файл

@ -0,0 +1,81 @@
namespace AngleSharp.Xml.Tests
{
using AngleSharp.Dom;
using AngleSharp.Io;
using AngleSharp.Svg.Dom;
using AngleSharp.Text;
using AngleSharp.Xml.Dom;
using AngleSharp.Xml.Parser;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
[TestFixture]
public class VariousTests
{
private static readonly String XmlContent = @"<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>";
private static readonly String SvgContent = @"
<svg xmlns=""http://www.w3.org/2000/svg"" viewBox=""0 0 100 100"">
<path d=""M34,93l11,-29a15,15 0,1,1 9,0l11,29a45,45 0,1,0 -31,0z"" stroke=""#142"" stroke-width=""2"" fill=""#4a5"" />
</svg>";
[Test]
public void ObtainElementPositionsFromXml()
{
var positions = new Dictionary<IElement, TextPosition>();
var source = @"<hello>
<foo />
<bar>
<test></test><test></test><test></test>
</bar>
</hello>";
var parser = new XmlParser(new XmlParserOptions
{
OnCreated = (element, position) => positions[element] = position
});
parser.ParseDocument(source);
Assert.AreEqual(6, positions.Count);
}
[Test]
public async Task GenerateDocumentFromXmlWithXmlContentType()
{
var document = await GenerateDocument(XmlContent, "text/xml");
Assert.IsInstanceOf<XmlDocument>(document);
Assert.AreEqual("note", document.DocumentElement.NodeName);
}
[Test]
public async Task GenerateDocumentFromSvgWithSvgContentType()
{
var document = await GenerateDocument(SvgContent, "image/svg+xml");
Assert.IsInstanceOf<SvgDocument>(document);
Assert.AreEqual("svg", document.DocumentElement.NodeName);
Assert.AreEqual("path", document.DocumentElement.FirstElementChild.NodeName);
}
private static Task<IDocument> GenerateDocument(String content, String contentType)
{
var config = Configuration.Default.WithDefaultLoader().WithXml();
var context = BrowsingContext.New(config);
return context.OpenAsync(res =>
{
res.Content(content);
if (!String.IsNullOrEmpty(contentType))
{
res.Header(HeaderNames.ContentType, contentType);
}
});
}
}
}

Просмотреть файл

@ -0,0 +1,135 @@
namespace AngleSharp.Xml.Tests.Xhtml
{
using AngleSharp.Dom;
using AngleSharp.Xhtml;
using NUnit.Framework;
using System.IO;
using System.Linq;
[TestFixture]
public class AutoSelectMarkupFormatter
{
[Test]
public void TestMetaTags()
{
var swResult = new StringWriter();
var document = (@"<!DOCTYPE html PUBLIC "" -//W3C//DTD XHTML 1.0 Strict//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"">
<html xmlns=""http://www.w3.org/1999/xhtml"">
<head>
<title>test.html</title>
<meta http-equiv=""Content-Type"" content=""text/html;charset=utf-8"" />
<meta name=""viewport"" content=""width=device-width"" />
</head>
<body>...</body>
</html>
").ToHtmlDocument();
document.ToHtml(swResult, new AutoSelectedMarkupFormatter(document.Doctype));
var result = swResult.ToString();
var c = 0;
var i = -1;
while ((i = result.IndexOf("/>", i + 1)) >= 0)
{
c++;
if (i >= result.Length)
{
Assert.Fail("End of result xhtml reached but not found what we are looking for!");
}
}
Assert.AreEqual(2, c);
Assert.AreEqual(-1, result.IndexOf("meta>"));
}
[Test]
public void TestImgTags()
{
var swResult = new StringWriter();
var document = (@"<!DOCTYPE html PUBLIC "" -//W3C//DTD XHTML 1.0 Strict//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"">
<html xmlns=""http://www.w3.org/1999/xhtml"">
<head>
<title>test.html</title>
</head>
<body>
<div>Image label1</div>
<img src=""/images/test1.png"" alt=""My Image1""/>
<div>Image label2</div>
<img src=""/images/test2.png"" alt=""My Image2""/>
</body>
</html>
").ToHtmlDocument();
document.ToHtml(swResult, new AutoSelectedMarkupFormatter(document.Doctype));
var result = swResult.ToString();
var c = 0;
var i = -1;
while ((i = result.IndexOf("/>", i + 1)) >= 0)
{
c++;
if (i >= result.Length)
{
Assert.Fail("End of result xhtml reached but not found what we are looking for!");
}
}
Assert.AreEqual(2, c);
Assert.AreEqual(-1, result.IndexOf("img>"));
}
[Test]
public void TestSomeComment()
{
var swResult = new StringWriter();
var source = @"<html xmlns=""http://www.w3.org/1999/xhtml"">
<head></head>
<!-- Comment -->
<body></body>
</html>";
var document = source.ToHtmlDocument();
document.ToHtml(swResult, new AutoSelectedMarkupFormatter(document.Doctype));
Assert.IsNotNull(swResult.ToString());
}
[Test]
public void TestTrailingComment()
{
var swResult = new StringWriter();
var source = @"<html xmlns=""http://www.w3.org/1999/xhtml"">
<head></head>
<body></body>
</html>
<!-- Comment -->";
var document = source.ToHtmlDocument();
document.ToHtml(swResult, new AutoSelectedMarkupFormatter(document.Doctype));
Assert.IsNotNull(swResult.ToString());
}
[Test]
public void TestRemovingComment()
{
var swResult = new StringWriter();
var source = @"<html xmlns=""http://www.w3.org/1999/xhtml"">
<head></head>
<body></body>
</html>
<!-- Comment -->";
var document = source.ToHtmlDocument();
var comments = document.Descendents<IComment>().ToList();
foreach (var comment in comments)
{
comment.Remove();
}
document.ToHtml(swResult, new AutoSelectedMarkupFormatter(document.Doctype));
Assert.IsNotNull(swResult.ToString());
}
}
}

Просмотреть файл

@ -0,0 +1,84 @@
namespace AngleSharp.Xml.Tests.Xhtml
{
using AngleSharp.Xhtml;
using NUnit.Framework;
using System.IO;
[TestFixture]
public class PreserveValidXhtml
{
[Test]
public void TestMetaTags()
{
var sw = new StringWriter();
var document = (@"<!DOCTYPE html PUBLIC "" -//W3C//DTD XHTML 1.0 Strict//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"">
<html xmlns=""http://www.w3.org/1999/xhtml"">
<head>
<title>test.html</title>
<meta http-equiv=""Content-Type"" content=""text/html;charset=utf-8"" />
<meta name=""viewport"" content=""width=device-width"" />
</head>
<body>...</body>
</html>
").ToXmlDocument();
document.ToHtml(sw, XhtmlMarkupFormatter.Instance);
var result = sw.ToString();
var c = 0;
var i = -1;
while ((i = result.IndexOf("/>", i + 1)) >= 0)
{
c++;
if (i >= result.Length)
{
Assert.Fail("End of result xhtml reached but not found what we are looking for!");
}
}
Assert.AreEqual(2, c);
Assert.AreEqual(-1, result.IndexOf("meta>"));
}
[Test]
public void TestImgTags()
{
var sw = new StringWriter();
var document = (@"<!DOCTYPE html PUBLIC "" -//W3C//DTD XHTML 1.0 Strict//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"">
<html xmlns=""http://www.w3.org/1999/xhtml"">
<head>
<title>test.html</title>
</head>
<body>
<div>Image label1</div>
<img src=""/images/test1.png"" alt=""My Image1""/>
<div>Image label2</div>
<img src=""/images/test2.png"" alt=""My Image2""/>
</body>
</html>
").ToXmlDocument();
document.ToHtml(sw, XhtmlMarkupFormatter.Instance);
var result = sw.ToString();
var c = 0;
var i = -1;
while ((i = result.IndexOf("/>", i + 1)) >= 0)
{
c++;
if (i >= result.Length)
{
Assert.Fail("End of result xhtml reached but not found what we are looking for!");
}
}
Assert.AreEqual(2, c);
Assert.AreEqual(-1, result.IndexOf("img>"));
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AngleSharp" version="0.10.0" targetFramework="net45" />
<package id="NUnit" version="3.4.1" targetFramework="net45" />
<package id="NUnit3TestAdapter" version="3.10.0" targetFramework="net45" />
</packages>

20
src/AngleSharp.Xml.nuspec Normal file
Просмотреть файл

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<package>
<metadata>
<id>AngleSharp.Io</id>
<version>$version$</version>
<authors>AngleSharp</authors>
<owners>Florian Rappl</owners>
<licenseUrl>https://github.com/AngleSharp/AngleSharp.Xml/blob/master/LICENSE</licenseUrl>
<projectUrl>https://anglesharp.github.io</projectUrl>
<iconUrl>https://raw.github.com/AngleSharp/AngleSharp.Xml/master/logo.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Adds a powerful XML and DTD parser to AngleSharp.</description>
<releaseNotes>https://github.com/AngleSharp/AngleSharp.Xml/blob/master/CHANGELOG.md</releaseNotes>
<copyright>Copyright 2016-2019, AngleSharp</copyright>
<tags>html html5 css css3 dom requester http https xml dtd</tags>
<dependencies>
<dependency id="AngleSharp" version="0.11.0" />
</dependencies>
</metadata>
</package>

28
src/AngleSharp.Xml.sln Normal file
Просмотреть файл

@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AngleSharp.Xml", "AngleSharp.Xml\AngleSharp.Xml.csproj", "{5B570639-7B4A-4A66-B283-9481F6A481ED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AngleSharp.Xml.Tests", "AngleSharp.Xml.Tests\AngleSharp.Xml.Tests.csproj", "{18B0B97B-8795-4DC2-A1E7-8070255BE718}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5B570639-7B4A-4A66-B283-9481F6A481ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B570639-7B4A-4A66-B283-9481F6A481ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B570639-7B4A-4A66-B283-9481F6A481ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B570639-7B4A-4A66-B283-9481F6A481ED}.Release|Any CPU.Build.0 = Release|Any CPU
{18B0B97B-8795-4DC2-A1E7-8070255BE718}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18B0B97B-8795-4DC2-A1E7-8070255BE718}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18B0B97B-8795-4DC2-A1E7-8070255BE718}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18B0B97B-8795-4DC2-A1E7-8070255BE718}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>AngleSharp.Xml</AssemblyName>
<RootNamespace>AngleSharp.Xml</RootNamespace>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0</TargetFrameworks>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AngleSharp" Version="0.11.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
</ItemGroup>
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<DelaySign>false</DelaySign>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,165 @@
namespace AngleSharp.Xml
{
using AngleSharp.Dom;
using AngleSharp.Html;
using AngleSharp.Xhtml;
using System;
/// <summary>
/// AutoSelectedMarkupFormatter class to select the proper MarkupFormatter
/// implementation depending on the used document type.
/// </summary>
public sealed class AutoSelectedMarkupFormatter : IMarkupFormatter
{
#region Fields
private IMarkupFormatter childFormatter = null;
private IDocumentType _docType;
#endregion
#region ctor
/// <summary>
/// Creates a new instance of the auto selected markup formatter.
/// </summary>
/// <param name="docType">
/// Optional DocumentType to hint the implementation to use.
/// </param>
public AutoSelectedMarkupFormatter(IDocumentType docType = null)
{
_docType = docType;
}
#endregion
#region Properties
private IMarkupFormatter ChildFormatter
{
get
{
if (childFormatter == null && _docType != null)
{
if (_docType.PublicIdentifier.Contains("XML"))
{
childFormatter = XmlMarkupFormatter.Instance;
}
else if (_docType.PublicIdentifier.Contains("XHTML"))
{
childFormatter = XhtmlMarkupFormatter.Instance;
}
}
return childFormatter ?? HtmlMarkupFormatter.Instance;
}
set
{
childFormatter = value;
}
}
#endregion
#region Methods
/// <summary>
/// Formats an attribute specified by the argument.
/// </summary>
/// <param name="attribute">The attribute to serialize.</param>
/// <returns>The formatted attribute.</returns>
public String Attribute(IAttr attribute)
{
return ChildFormatter.Attribute(attribute);
}
/// <summary>
/// Formats opening a tag with the given name.
/// </summary>
/// <param name="element">The element to open.</param>
/// <param name="selfClosing">
/// Is the element actually self-closing?
/// </param>
/// <returns>The formatted opening tag.</returns>
public String OpenTag(IElement element, Boolean selfClosing)
{
Confirm(element.Owner.Doctype);
return ChildFormatter.OpenTag(element, selfClosing);
}
/// <summary>
/// Formats closing a tag with the given name.
/// </summary>
/// <param name="element">The element to close.</param>
/// <param name="selfClosing">
/// Is the element actually self-closing?
/// </param>
/// <returns>The formatted closing tag.</returns>
public String CloseTag(IElement element, Boolean selfClosing)
{
Confirm(element.Owner.Doctype);
return ChildFormatter.CloseTag(element, selfClosing);
}
/// <summary>
/// Formats the given comment.
/// </summary>
/// <param name="comment">The comment to stringify.</param>
/// <returns>The formatted comment.</returns>
public String Comment(IComment comment)
{
Confirm(comment.Owner.Doctype);
return ChildFormatter.Comment(comment);
}
/// <summary>
/// Formats the given doctype using the name, public and system
/// identifiers.
/// </summary>
/// <param name="doctype">The document type to stringify.</param>
/// <returns>The formatted doctype.</returns>
public String Doctype(IDocumentType doctype)
{
Confirm(doctype);
return ChildFormatter.Doctype(doctype);
}
/// <summary>
/// Formats the given processing instruction using the target and the
/// data.
/// </summary>
/// <param name="processing">
/// The processing instruction to stringify.
/// </param>
/// <returns>The formatted processing instruction.</returns>
public String Processing(IProcessingInstruction processing)
{
Confirm(processing.Owner.Doctype);
return ChildFormatter.Processing(processing);
}
/// <summary>
/// Formats the given text.
/// </summary>
/// <param name="text">The text to sanatize.</param>
/// <returns>The formatted text.</returns>
public String Text(ICharacterData text)
{
return ChildFormatter.Text(text);
}
#endregion
#region Helpers
private void Confirm(IDocumentType docType)
{
if (_docType == null)
{
_docType = docType;
}
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,32 @@
namespace AngleSharp.Xml.Dom.Events
{
using AngleSharp.Dom;
using AngleSharp.Dom.Events;
using System;
/// <summary>
/// The event that is published in case of starting XML parsing.
/// </summary>
public class XmlParseEvent : Event
{
/// <summary>
/// Creates a new event for starting XML parsing.
/// </summary>
/// <param name="document">The document to be filled.</param>
/// <param name="completed">Determines if parsing is done.</param>
public XmlParseEvent(IDocument document, Boolean completed)
: base(completed ? EventNames.Parsed : EventNames.Parsing)
{
Document = document;
}
/// <summary>
/// Gets the document, which is to be filled.
/// </summary>
public IDocument Document
{
get;
private set;
}
}
}

Просмотреть файл

@ -0,0 +1,18 @@
namespace AngleSharp.Svg.Dom
{
using AngleSharp.Attributes;
using AngleSharp.Dom;
/// <summary>
/// Serves as an entry point to the content of an SVG document.
/// </summary>
[DomName("SVGDocument")]
public interface ISvgDocument : IDocument
{
/// <summary>
/// Gets the root svg element in the document hierachy.
/// </summary>
[DomName("rootElement")]
ISvgSvgElement RootElement { get; }
}
}

Просмотреть файл

@ -0,0 +1,13 @@
namespace AngleSharp.Xml.Dom
{
using AngleSharp.Attributes;
using AngleSharp.Dom;
/// <summary>
/// The interface represent an XML document.
/// </summary>
[DomName("XMLDocument")]
public interface IXmlDocument : IDocument
{
}
}

Просмотреть файл

@ -0,0 +1,94 @@
namespace AngleSharp.Svg.Dom
{
using AngleSharp.Dom;
using AngleSharp.Io;
using AngleSharp.Text;
using AngleSharp.Xml;
using System;
/// <summary>
/// Represents a document node that contains only SVG nodes.
/// </summary>
sealed class SvgDocument : Document, ISvgDocument
{
#region Fields
private readonly IElementFactory<Document, ISvgElement> _factory;
#endregion
#region ctor
internal SvgDocument(IBrowsingContext context, TextSource source)
: base(context ?? BrowsingContext.New(), source)
{
ContentType = MimeTypeNames.Svg;
_factory = Context.GetFactory<IElementFactory<Document, ISvgElement>>();
}
internal SvgDocument(IBrowsingContext context = null)
: this(context, new TextSource(String.Empty))
{
}
#endregion
#region Properties
public override IElement DocumentElement
{
get { return RootElement; }
}
public ISvgSvgElement RootElement
{
get { return this.FindChild<ISvgSvgElement>(); }
}
public override IEntityProvider Entities
{
get { return Context.GetProvider<IEntityProvider>() ?? XmlEntityProvider.Resolver; }
}
#endregion
#region Methods
public override Element CreateElementFrom(String name, String prefix)
{
return _factory.Create(this, name, prefix) as Element;
}
public override Node Clone(Document owner, Boolean deep)
{
var node = new SvgDocument(Context, new TextSource(Source.Text));
CloneDocument(node, deep);
return node;
}
#endregion
#region Helpers
protected override String GetTitle()
{
var title = RootElement.FindChild<ISvgTitleElement>();
return title?.TextContent.CollapseAndStrip() ?? base.GetTitle();
}
protected override void SetTitle(String value)
{
ISvgElement title = RootElement.FindChild<ISvgTitleElement>();
if (title == null)
{
title = _factory.Create(this, TagNames.Title);
RootElement.AppendChild(title);
}
title.TextContent = value;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,66 @@
namespace AngleSharp.Xml.Dom
{
using AngleSharp.Dom;
using AngleSharp.Io;
using AngleSharp.Text;
using System;
/// <summary>
/// Represents a document node that contains only XML nodes.
/// </summary>
sealed class XmlDocument : Document, IXmlDocument
{
#region ctor
internal XmlDocument(IBrowsingContext context, TextSource source)
: base(context ?? BrowsingContext.New(), source)
{
ContentType = MimeTypeNames.Xml;
}
internal XmlDocument(IBrowsingContext context = null)
: this(context, new TextSource(String.Empty))
{
}
#endregion
#region Properties
public override IElement DocumentElement
{
get { return this.FindChild<IElement>(); }
}
public override IEntityProvider Entities
{
get { return Context.GetProvider<IEntityProvider>() ?? XmlEntityProvider.Resolver; }
}
#endregion
#region Methods
public override Element CreateElementFrom(String name, String prefix)
{
return new XmlElement(this, name, prefix);
}
public override Node Clone(Document owner, Boolean deep)
{
var node = new XmlDocument(Context, new TextSource(Source.Text));
CloneDocument(node, deep);
return node;
}
#endregion
#region Helpers
protected override void SetTitle(String value)
{
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,42 @@
namespace AngleSharp.Xml.Dom
{
using AngleSharp.Dom;
using System;
/// <summary>
/// The object representation of an XMLElement.
/// </summary>
sealed class XmlElement : Element
{
#region ctor
public XmlElement(Document owner, String name, String prefix = null)
: base(owner, name, prefix, null)
{
}
#endregion
#region Properties
internal String IdAttribute
{
get;
set;
}
#endregion
#region Methods
public override Node Clone(Document owner, Boolean deep)
{
var node = new XmlElement(owner, LocalName, Prefix);
CloneElement(node, owner, deep);
node.IdAttribute = IdAttribute;
return node;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,54 @@
namespace AngleSharp.Xml
{
using AngleSharp.Attributes;
using AngleSharp.Dom;
using AngleSharp.Xml.Dom;
using System;
/// <summary>
/// Extensions for the DomImplementation interface.
/// </summary>
[DomExposed("DOMImplementation")]
public static class DomImplementationExtension
{
/// <summary>
/// Creates and returns an XMLDocument.
/// </summary>
/// <param name="namespaceUri">
/// The namespace URI of the document to be created, or null if the
/// document doesn't belong to one.
/// </param>
/// <param name="qualifiedName">
/// The qualified name, that is an optional prefix and colon plus the
/// local root element name, of the document to be created.
/// </param>
/// <param name="doctype">
/// DocumentType of the document to be created. It defaults to null.
/// </param>
/// <returns>A new document.</returns>
[DomName("createDocument")]
public static IXmlDocument CreateDocument(this IImplementation impl, String namespaceUri = null, String qualifiedName = null, IDocumentType doctype = null)
{
var document = new XmlDocument();
if (doctype != null)
{
document.AppendChild(doctype);
}
if (!String.IsNullOrEmpty(qualifiedName))
{
var element = document.CreateElement(namespaceUri, qualifiedName);
if (element != null)
{
document.AppendChild(element);
}
}
document.BaseUrl = _owner.BaseUrl;
return document;
}
}
}

Двоичные данные
src/AngleSharp.Xml/Key.snk Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,41 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Browser;
using AngleSharp.Dom;
using AngleSharp.Xml.Dom;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Represents the interface of an XML parser.
/// </summary>
public interface IXmlParser : IParser
{
/// <summary>
/// Parses the string and returns the result.
/// </summary>
IXmlDocument ParseDocument(String source);
/// <summary>
/// Parses the stream and returns the result.
/// </summary>
IXmlDocument ParseDocument(Stream source);
/// <summary>
/// Parses the string asynchronously with option to cancel.
/// </summary>
Task<IXmlDocument> ParseDocumentAsync(String source, CancellationToken cancel);
/// <summary>
/// Parses the stream asynchronously with option to cancel.
/// </summary>
Task<IXmlDocument> ParseDocumentAsync(Stream source, CancellationToken cancel);
/// <summary>
/// Populates the given document asynchronously.
/// </summary>
Task<IDocument> ParseDocumentAsync(IDocument document, CancellationToken cancel);
}
}

Просмотреть файл

@ -0,0 +1,47 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// The CData token that contains a sequence of raw characters.
/// </summary>
sealed class XmlCDataToken : XmlToken
{
#region Fields
private readonly String _data;
#endregion
#region ctor
/// <summary>
/// Creates a new CData token.
/// </summary>
public XmlCDataToken(TextPosition position)
: this(position, String.Empty)
{
}
/// <summary>
/// Creates a new CData token with the supplied data.
/// </summary>
public XmlCDataToken(TextPosition position, String data)
: base(XmlTokenType.CData, position)
{
_data = data;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the supplied data.
/// </summary>
public String Data => _data;
#endregion
}
}

Просмотреть файл

@ -0,0 +1,52 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// The character token that contains a single character.
/// </summary>
sealed class XmlCharacterToken : XmlToken
{
#region Fields
private readonly String _data;
#endregion
#region ctor
/// <summary>
/// Creates a new character token.
/// </summary>
public XmlCharacterToken(TextPosition position)
: this(position, String.Empty)
{
}
/// <summary>
/// Creates a new character token with the given character.
/// </summary>
public XmlCharacterToken(TextPosition position, String data)
: base(XmlTokenType.Character, position)
{
_data = data;
}
#endregion
#region Properties
/// <summary>
/// Gets if the token only contains spaces.
/// </summary>
public override Boolean IsIgnorable => _data.StripLeadingTrailingSpaces().Length == 0;
/// <summary>
/// Gets the data of the character token.
/// </summary>
public String Data => _data;
#endregion
}
}

Просмотреть файл

@ -0,0 +1,47 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// The token that is used for comments.
/// </summary>
sealed class XmlCommentToken : XmlToken
{
#region Fields
private readonly String _data;
#endregion
#region ctor
/// <summary>
/// Creates a new comment token.
/// </summary>
public XmlCommentToken(TextPosition position)
: this(position, String.Empty)
{
}
/// <summary>
/// Creates a new comment token with the supplied data.
/// </summary>
public XmlCommentToken(TextPosition position, String data)
: base(XmlTokenType.Comment, position)
{
_data = data;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the supplied data.
/// </summary>
public String Data => _data;
#endregion
}
}

Просмотреть файл

@ -0,0 +1,70 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// Represents the XML declaration &lt;?xml ...?&gt;
/// </summary>
sealed class XmlDeclarationToken : XmlToken
{
#region Fields
private String _version;
private String _encoding;
private Boolean _standalone;
#endregion
#region ctor
/// <summary>
/// Creates a new XML declaration token.
/// </summary>
public XmlDeclarationToken(TextPosition position)
: base(XmlTokenType.Declaration, position)
{
_version = String.Empty;
_encoding = null;
_standalone = false;
}
#endregion
#region Properties
/// <summary>
/// Gets if the encoding value has been set.
/// </summary>
public Boolean IsEncodingMissing => _encoding == null;
/// <summary>
/// Gets or sets the version value.
/// </summary>
public String Version
{
get { return _version; }
set { _version = value; }
}
/// <summary>
/// Gets or sets the encoding value.
/// </summary>
public String Encoding
{
get { return _encoding ?? String.Empty; }
set { _encoding = value; }
}
/// <summary>
/// Gets or sets the standalone value.
/// </summary>
public Boolean Standalone
{
get { return _standalone; }
set { _standalone = value; }
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,89 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// The DOCTYPE token.
/// </summary>
sealed class XmlDoctypeToken : XmlToken
{
#region Fields
private String _name;
private String _publicIdentifier;
private String _systemIdentifier;
#endregion
#region ctor
/// <summary>
/// Creates a new DOCTYPE token.
/// </summary>
public XmlDoctypeToken(TextPosition position)
: base(XmlTokenType.Doctype, position)
{
_name = null;
_publicIdentifier = null;
_systemIdentifier = null;
}
#endregion
#region Properties
/// <summary>
/// Gets the state of the name.
/// </summary>
public Boolean IsNameMissing => _name == null;
/// <summary>
/// Gets the state of the public identifier.
/// </summary>
public Boolean IsPublicIdentifierMissing => _publicIdentifier == null;
/// <summary>
/// Gets the state of the system identifier.
/// </summary>
public Boolean IsSystemIdentifierMissing => _systemIdentifier == null;
/// <summary>
/// Gets or sets the name of the DOCTYPE token.
/// </summary>
public String Name
{
get { return _name ?? String.Empty; }
set { _name = value; }
}
/// <summary>
/// Gets or sets the value of the public identifier.
/// </summary>
public String PublicIdentifier
{
get { return _publicIdentifier ?? String.Empty; }
set { _publicIdentifier = value; }
}
/// <summary>
/// Gets or sets the value of the system identifier.
/// </summary>
public String SystemIdentifier
{
get { return _systemIdentifier ?? String.Empty; }
set { _systemIdentifier = value; }
}
/// <summary>
/// Gets or sets the internal subset.
/// </summary>
public String InternalSubset
{
get;
set;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,18 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
/// <summary>
/// Represents the final token to mark the EOF.
/// </summary>
sealed class XmlEndOfFileToken : XmlToken
{
/// <summary>
/// Creates a new EOF token.
/// </summary>
public XmlEndOfFileToken(TextPosition position)
: base(XmlTokenType.EndOfFile, position)
{
}
}
}

Просмотреть файл

@ -0,0 +1,54 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// The processing instruction token that defines a processing instruction.
/// </summary>
sealed class XmlPIToken : XmlToken
{
#region Fields
private String _target;
private String _content;
#endregion
#region ctor
/// <summary>
/// Creates a new processing instruction token.
/// </summary>
public XmlPIToken(TextPosition position)
: base(XmlTokenType.ProcessingInstruction, position)
{
_target = String.Empty;
_content = String.Empty;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the target data.
/// </summary>
public String Target
{
get { return _target; }
set { _target = value; }
}
/// <summary>
/// Gets or sets the content data.
/// </summary>
public String Content
{
get { return _content; }
set { _content = value; }
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,113 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
using System.Collections.Generic;
/// <summary>
/// Class for StartTagToken and EndTagToken.
/// </summary>
sealed class XmlTagToken : XmlToken
{
#region Fields
private readonly List<KeyValuePair<String, String>> _attributes;
private String _name;
private Boolean _selfClosing;
#endregion
#region ctor
/// <summary>
/// Sets the default values.
/// </summary>
public XmlTagToken(XmlTokenType type, TextPosition position)
: base(type, position)
{
_name = String.Empty;
_attributes = new List<KeyValuePair<String, String>>();
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the state of the self-closing flag.
/// </summary>
public Boolean IsSelfClosing
{
get { return _selfClosing; }
set { _selfClosing = value; }
}
/// <summary>
/// Gets or sets the name of the tag.
/// </summary>
public String Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// Gets the list of attributes.
/// </summary>
public List<KeyValuePair<String, String>> Attributes => _attributes;
#endregion
#region Methods
/// <summary>
/// Adds a new attribute to the list of attributes. The value will
/// be set to an empty string.
/// </summary>
/// <param name="name">The name of the attribute.</param>
public void AddAttribute(String name)
{
_attributes.Add(new KeyValuePair<String, String>(name, String.Empty));
}
/// <summary>
/// Adds a new attribute to the list of attributes.
/// </summary>
/// <param name="name">The name of the attribute.</param>
/// <param name="value">The value of the attribute.</param>
public void AddAttribute(String name, String value)
{
_attributes.Add(new KeyValuePair<String, String>(name, value));
}
/// <summary>
/// Sets the value of the last added attribute.
/// </summary>
/// <param name="value">The value to set.</param>
public void SetAttributeValue(String value)
{
_attributes[_attributes.Count - 1] = new KeyValuePair<String, String>(_attributes[_attributes.Count - 1].Key, value);
}
/// <summary>
/// Gets the value of the attribute with the given name or an empty
/// string if the attribute is not available.
/// </summary>
/// <param name="name">The name of the attribute.</param>
/// <returns>The value of the attribute.</returns>
public String GetAttribute(String name)
{
for (var i = 0; i != _attributes.Count; i++)
{
if (_attributes[i].Key.Is(name))
{
return _attributes[i].Value;
}
}
return String.Empty;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,47 @@
namespace AngleSharp.Xml.Parser.Tokens
{
using AngleSharp.Text;
using System;
/// <summary>
/// The abstract base class of any XML token.
/// </summary>
abstract class XmlToken
{
#region Fields
private readonly XmlTokenType _type;
private readonly TextPosition _position;
#endregion
#region ctor
public XmlToken(XmlTokenType type, TextPosition position)
{
_type = type;
_position = position;
}
#endregion
#region Properties
/// <summary>
/// Gets if the token can be ignored.
/// </summary>
public virtual Boolean IsIgnorable => false;
/// <summary>
/// Gets the type of the token.
/// </summary>
public XmlTokenType Type => _type;
/// <summary>
/// Gets the position of the token.
/// </summary>
public TextPosition Position => _position;
#endregion
}
}

Просмотреть файл

@ -0,0 +1,457 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Dom;
using AngleSharp.Text;
using AngleSharp.Xml.Dom;
using AngleSharp.Xml.Parser.Tokens;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Represents the Tree construction as specified in the official W3C
/// specification for XML:
/// http://www.w3.org/TR/REC-xml/
/// </summary>
sealed class XmlDomBuilder
{
#region Fields
private readonly XmlTokenizer _tokenizer;
private readonly Document _document;
private readonly List<Element> _openElements;
private XmlParserOptions _options;
private XmlTreeMode _currentMode;
private Boolean _standalone;
#endregion
#region ctor
/// <summary>
/// Creates a new instance of the XML parser.
/// </summary>
/// <param name="document">The document instance to be filled.</param>
internal XmlDomBuilder(Document document)
{
_tokenizer = new XmlTokenizer(document.Source, document.Entities);
_document = document;
_standalone = false;
_openElements = new List<Element>();
_currentMode = XmlTreeMode.Initial;
}
#endregion
#region Properties
/// <summary>
/// Gets if the document was detected to be standalone.
/// </summary>
public Boolean IsStandalone => _standalone;
/// <summary>
/// Gets the current node.
/// </summary>
public Node CurrentNode
{
get
{
if (_openElements.Count > 0)
{
return _openElements[_openElements.Count - 1];
}
return _document;
}
}
#endregion
#region Methods
/// <summary>
/// Parses the given source asynchronously and creates the document.
/// </summary>
/// <param name="options">The options to use for parsing.</param>
/// <param name="cancelToken">The cancellation token to use.</param>
public async Task<Document> ParseAsync(XmlParserOptions options, CancellationToken cancelToken)
{
var source = _document.Source;
var token = default(XmlToken);
_options = options;
_tokenizer.IsSuppressingErrors = options.IsSuppressingErrors;
do
{
if (source.Length - source.Index < 1024)
{
await source.PrefetchAsync(8192, cancelToken).ConfigureAwait(false);
}
token = _tokenizer.Get();
Consume(token);
}
while (token.Type != XmlTokenType.EndOfFile);
return _document;
}
/// <summary>
/// Parses the given source and creates the document.
/// </summary>
/// <param name="options">The options to use for parsing.</param>
public Document Parse(XmlParserOptions options)
{
var token = default(XmlToken);
_options = options;
_tokenizer.IsSuppressingErrors = options.IsSuppressingErrors;
do
{
token = _tokenizer.Get();
Consume(token);
}
while (token.Type != XmlTokenType.EndOfFile);
return _document;
}
#endregion
#region States
/// <summary>
/// Consumes a token and processes it.
/// </summary>
/// <param name="token">The token to consume.</param>
private void Consume(XmlToken token)
{
switch (_currentMode)
{
case XmlTreeMode.Initial:
Initial(token);
break;
case XmlTreeMode.Prolog:
BeforeDoctype(token);
break;
case XmlTreeMode.Misc:
InMisc(token);
break;
case XmlTreeMode.Body:
InBody(token);
break;
case XmlTreeMode.After:
AfterBody(token);
break;
}
}
/// <summary>
/// The initial state. Expects an XML declaration.
/// </summary>
/// <param name="token">The consumed token.</param>
private void Initial(XmlToken token)
{
if (token.Type == XmlTokenType.Declaration)
{
var declarationToken = (XmlDeclarationToken)token;
_standalone = declarationToken.Standalone;
if (!declarationToken.IsEncodingMissing)
{
SetEncoding(declarationToken.Encoding);
}
if (!CheckVersion(declarationToken.Version) && !_options.IsSuppressingErrors)
{
throw XmlParseError.XmlDeclarationVersionUnsupported.At(token.Position);
}
}
else
{
_currentMode = XmlTreeMode.Prolog;
BeforeDoctype(token);
}
}
/// <summary>
/// Before any doctype - still in the prolog. No declaration
/// allowed.
/// </summary>
/// <param name="token">The consumed token.</param>
private void BeforeDoctype(XmlToken token)
{
switch (token.Type)
{
case XmlTokenType.Doctype:
{
var doctypeToken = (XmlDoctypeToken)token;
var doctypeNode = _document.Implementation.CreateDocumentType(doctypeToken.Name, doctypeToken.PublicIdentifier, doctypeToken.SystemIdentifier);
_document.AppendChild(doctypeNode);
_currentMode = XmlTreeMode.Misc;
break;
}
default:
{
InMisc(token);
break;
}
}
}
/// <summary>
/// In the body state - no doctypes and declarations allowed.
/// </summary>
/// <param name="token">The consumed token.</param>
private void InMisc(XmlToken token)
{
switch (token.Type)
{
case XmlTokenType.Comment:
{
var commenToken = (XmlCommentToken)token;
var commentNode = _document.CreateComment(commenToken.Data);
CurrentNode.AppendChild(commentNode);
break;
}
case XmlTokenType.ProcessingInstruction:
{
var piToken = (XmlPIToken)token;
var piNode = _document.CreateProcessingInstruction(piToken.Target, piToken.Content);
CurrentNode.AppendChild(piNode);
break;
}
case XmlTokenType.StartTag:
{
_currentMode = XmlTreeMode.Body;
InBody(token);
break;
}
default:
{
if (!token.IsIgnorable && !_options.IsSuppressingErrors)
{
throw XmlParseError.XmlMissingRoot.At(token.Position);
}
break;
}
}
}
/// <summary>
/// In the body state - no doctypes and declarations allowed.
/// </summary>
/// <param name="token">The consumed token.</param>
private void InBody(XmlToken token)
{
switch (token.Type)
{
case XmlTokenType.StartTag:
{
var tagToken = (XmlTagToken)token;
var element = CreateElement(tagToken.Name);
CurrentNode.AppendChild(element);
for (var i = 0; i < tagToken.Attributes.Count; i++)
{
var attr = tagToken.Attributes[i];
var item = CreateAttribute(attr.Key, attr.Value.Trim());
element.AddAttribute(item);
}
if (!tagToken.IsSelfClosing)
{
_openElements.Add(element);
}
else if (_openElements.Count == 0)
{
_currentMode = XmlTreeMode.After;
}
if (_options.OnCreated != null)
{
_options.OnCreated.Invoke(element, tagToken.Position);
}
break;
}
case XmlTokenType.EndTag:
{
var tagToken = (XmlTagToken)token;
if (!CurrentNode.NodeName.Is(tagToken.Name))
{
if (_options.IsSuppressingErrors)
{
break;
}
throw XmlParseError.TagClosingMismatch.At(token.Position);
}
_openElements.RemoveAt(_openElements.Count - 1);
if (_openElements.Count == 0)
{
_currentMode = XmlTreeMode.After;
}
break;
}
case XmlTokenType.ProcessingInstruction:
case XmlTokenType.Comment:
{
InMisc(token);
break;
}
case XmlTokenType.CData:
{
var cdataToken = (XmlCDataToken)token;
CurrentNode.AppendText(cdataToken.Data);
break;
}
case XmlTokenType.Character:
{
var charToken = (XmlCharacterToken)token;
CurrentNode.AppendText(charToken.Data);
break;
}
case XmlTokenType.EndOfFile:
{
if (_options.IsSuppressingErrors)
{
break;
}
throw XmlParseError.EOF.At(token.Position);
}
case XmlTokenType.Doctype:
{
if (_options.IsSuppressingErrors)
{
break;
}
throw XmlParseError.XmlDoctypeAfterContent.At(token.Position);
}
case XmlTokenType.Declaration:
{
if (_options.IsSuppressingErrors)
{
break;
}
throw XmlParseError.XmlDeclarationMisplaced.At(token.Position);
}
}
}
/// <summary>
/// After the body state - nothing except Comment PI S allowed.
/// </summary>
/// <param name="token">The consumed token.</param>
private void AfterBody(XmlToken token)
{
switch (token.Type)
{
case XmlTokenType.ProcessingInstruction:
case XmlTokenType.Comment:
{
InMisc(token);
break;
}
case XmlTokenType.EndOfFile:
{
break;
}
default:
{
if (!token.IsIgnorable && !_options.IsSuppressingErrors)
{
throw XmlParseError.XmlMissingRoot.At(token.Position);
}
break;
}
}
}
#endregion
#region Helpers
private static Element CreateElement(Document document, String name, String prefix)
{
return new XmlElement(document, name, prefix);
}
private Element CreateElement(String name)
{
var prefix = default(String);
var colon = name.IndexOf(Symbols.Colon);
if (colon > 0 && colon < name.Length - 1)
{
prefix = name.Substring(0, colon);
name = name.Substring(colon + 1);
}
return _document.CreateElementFrom(name, prefix);
}
private Attr CreateAttribute(String name, String value)
{
var colon = name.IndexOf(Symbols.Colon);
if (colon > 0 && colon < name.Length - 1)
{
var prefix = name.Substring(0, colon);
var ns = NamespaceNames.XmlNsUri;
if (!prefix.Is(NamespaceNames.XmlNsPrefix))
{
ns = CurrentNode.LookupNamespaceUri(prefix);
}
return new Attr(prefix, name.Substring(colon + 1), value, ns);
}
return new Attr(name, value);
}
private static Boolean CheckVersion(String ver)
{
var t = ver.ToDouble(0.0);
return t >= 1.0 && t < 2.0;
}
private void SetEncoding(String charSet)
{
if (TextEncoding.IsSupported(charSet))
{
var encoding = TextEncoding.Resolve(charSet);
if (encoding != null)
{
try
{
_document.Source.CurrentEncoding = encoding;
}
catch (NotSupportedException)
{
_currentMode = XmlTreeMode.Initial;
_document.Clear();
_openElements.Clear();
}
}
}
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,153 @@
namespace AngleSharp.Xml.Parser
{
/// <summary>
/// A collection of error codes.
/// </summary>
enum XmlParseError : ushort
{
/// <summary>
/// Unexpected end of file detected.
/// </summary>
EOF = 0x00,
/// <summary>
/// Undefined markup declaration found.
/// </summary>
UndefinedMarkupDeclaration = 0x1e,
/// <summary>
/// Character reference is an invalid number.
/// </summary>
CharacterReferenceInvalidNumber = 0x38,
/// <summary>
/// Character reference is an invalid code.
/// </summary>
CharacterReferenceInvalidCode = 0x39,
/// <summary>
/// Character reference is not terminated by a semicolon.
/// </summary>
CharacterReferenceNotTerminated = 0x3a,
/// <summary>
/// The given doctype tag is invalid.
/// </summary>
DoctypeInvalid = 0x45,
/// <summary>
/// The closing tag and the currently open tag do not match.
/// </summary>
TagClosingMismatch = 0x76,
/// <summary>
/// (0x200) Missing root element.
/// </summary>
XmlMissingRoot = 0x200,
/// <summary>
/// (0x201) Document type declaration after content.
/// </summary>
XmlDoctypeAfterContent = 0x201,
/// <summary>
/// (0x202) Invalid XML declaration.
/// </summary>
XmlDeclarationInvalid = 0x202,
/// <summary>
/// (0x203) XML declaration not at beginning of document.
/// </summary>
XmlDeclarationMisplaced = 0x203,
/// <summary>
/// (0x204) The given version number is not supported.
/// </summary>
XmlDeclarationVersionUnsupported = 0x204,
/// <summary>
/// (0x205) Invalid start-tag.
/// </summary>
XmlInvalidStartTag = 0x205,
/// <summary>
/// (0x206) Invalid end-tag.
/// </summary>
XmlInvalidEndTag = 0x206,
/// <summary>
/// (0x207) Well-formedness constraint: No &lt; in Attribute Values.
/// </summary>
XmlLtInAttributeValue = 0x207,
/// <summary>
/// (0x208) Well-formedness constraint: Unique Att Spec.
/// </summary>
XmlUniqueAttribute = 0x208,
/// <summary>
/// (0x209) Invalid processing instruction.
/// </summary>
XmlInvalidPI = 0x209,
/// <summary>
/// (0x210) XML validation for the current document failed.
/// </summary>
XmlValidationFailed = 0x210,
/// <summary>
/// (0x211) XML invalid character data detected.
/// </summary>
XmlInvalidCharData = 0x211,
/// <summary>
/// (0x212) XML invalid name found.
/// </summary>
XmlInvalidName = 0x212,
/// <summary>
/// (0x213) XML invalid public identifier character.
/// </summary>
XmlInvalidPubId = 0x213,
/// <summary>
/// (0x214) XML invalid attribute seen.
/// </summary>
XmlInvalidAttribute = 0x214,
/// <summary>
/// (0x215) XML invalid comment detected.
/// </summary>
XmlInvalidComment = 0x215,
/// <summary>
/// (0x300) Invalid document type declaration.
/// </summary>
DtdInvalid = 0x300,
/// <summary>
/// (0x301) Invalid parameter entity reference.
/// </summary>
DtdPEReferenceInvalid = 0x301,
/// <summary>
/// (0x302) Invalid name in entity declaration.
/// </summary>
DtdNameInvalid = 0x302,
/// <summary>
/// (0x303) Declaration invalid.
/// </summary>
DtdDeclInvalid = 0x303,
/// <summary>
/// (0x304) Invalid element type declaration.
/// </summary>
DtdTypeInvalid = 0x304,
/// <summary>
/// (0x305) Invalid entity declaration.
/// </summary>
DtdEntityInvalid = 0x305,
/// <summary>
/// (0x306) Invalid element name in attribute-list declaration.
/// </summary>
DtdAttListInvalid = 0x306,
/// <summary>
/// (0x307) Invalid content specification in element type declaration.
/// </summary>
DtdTypeContent = 0x307,
/// <summary>
/// (0x308) An element type must not be declared more than once.
/// </summary>
DtdUniqueElementViolated = 0x308,
/// <summary>
/// (0x309) The DTD conditional section is invalid.
/// </summary>
DtdConditionInvalid = 0x309,
/// <summary>
/// (0x310) The given text declaration contains errors.s
/// </summary>
DtdTextDeclInvalid = 0x310,
/// <summary>
/// (0x311) The notation declaration is invalid.
/// </summary>
DtdNotationInvalid = 0x311,
/// <summary>
/// (0x312) No parameter reference recursion allowed.
/// </summary>
DtdPEReferenceRecursion = 0x312,
}
}

Просмотреть файл

@ -0,0 +1,33 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Text;
using System;
/// <summary>
/// Extensions for the parse error enumeration.
/// </summary>
static class XmlParseErrorExtensions
{
/// <summary>
/// Creates the XmlParseException at the given position.
/// </summary>
/// <param name="code">The code for the exception.</param>
/// <param name="position">The position of the error.</param>
/// <returns>The new exception object.</returns>
public static XmlParseException At(this XmlParseError code, TextPosition position)
{
var message = "Error while parsing the provided XML document.";
return new XmlParseException(code.GetCode(), message, position);
}
/// <summary>
/// Retrieves a number describing the error of a given error code.
/// </summary>
/// <param name="code">A specific error code.</param>
/// <returns>The code of the error.</returns>
public static Int32 GetCode(this XmlParseError code)
{
return (Int32)code;
}
}
}

Просмотреть файл

@ -0,0 +1,51 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Text;
using System;
/// <summary>
/// Exception that is thrown if an ill-formatted XML document is parsed.
/// </summary>
public class XmlParseException : Exception
{
#region ctor
/// <summary>
/// Creates a new XmlParseException.
/// </summary>
/// <param name="code">The provided error code.</param>
/// <param name="message">The associated error message.</param>
/// <param name="position">The position in the source.</param>
///
public XmlParseException(Int32 code, String message, TextPosition position)
: base(message)
{
Code = code;
Position = position;
}
#endregion
#region Properties
/// <summary>
/// Gets the position of the error.
/// </summary>
public TextPosition Position
{
get;
private set;
}
/// <summary>
/// Gets the provided error code.
/// </summary>
public Int32 Code
{
get;
private set;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,206 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Dom;
using AngleSharp.Text;
using AngleSharp.Xml.Dom;
using AngleSharp.Xml.Dom.Events;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Creates an instance of the XML parser front-end.
/// </summary>
public class XmlParser : EventTarget, IXmlParser
{
#region Fields
private readonly XmlParserOptions _options;
private readonly IBrowsingContext _context;
#endregion
#region Events
/// <summary>
/// Fired when the XML parser is starting.
/// </summary>
public event DomEventHandler Parsing
{
add { AddEventListener(EventNames.Parsing, value); }
remove { RemoveEventListener(EventNames.Parsing, value); }
}
/// <summary>
/// Fired when the XML parser is finished.
/// </summary>
public event DomEventHandler Parsed
{
add { AddEventListener(EventNames.Parsed, value); }
remove { RemoveEventListener(EventNames.Parsed, value); }
}
/// <summary>
/// Fired when a XML parse error is encountered.
/// </summary>
public event DomEventHandler Error
{
add { AddEventListener(EventNames.Error, value); }
remove { RemoveEventListener(EventNames.Error, value); }
}
#endregion
#region ctor
/// <summary>
/// Creates a new parser with the default options and context.
/// </summary>
public XmlParser()
: this(default(IBrowsingContext))
{
}
/// <summary>
/// Creates a new parser with the custom options.
/// </summary>
/// <param name="options">The options to use.</param>
public XmlParser(XmlParserOptions options)
: this(options, default(IBrowsingContext))
{
}
/// <summary>
/// Creates a new parser with the custom configuration.
/// </summary>
/// <param name="context">The context to use.</param>
internal XmlParser(IBrowsingContext context)
: this(default(XmlParserOptions), context)
{
}
/// <summary>
/// Creates a new parser with the custom options and the given context.
/// </summary>
/// <param name="options">The options to use.</param>
/// <param name="context">The context to use.</param>
public XmlParser(XmlParserOptions options, IBrowsingContext context)
{
_options = options;
_context = context ?? BrowsingContext.NewFrom<IXmlParser>(this);
}
#endregion
#region Properties
/// <summary>
/// Gets the specified options.
/// </summary>
public XmlParserOptions Options => _options;
/// <summary>
/// Gets the specified context.
/// </summary>
public IBrowsingContext Context => _context;
#endregion
#region Methods
/// <summary>
/// Parses the string and returns the result.
/// </summary>
public IXmlDocument ParseDocument(String source)
{
var document = CreateDocument(source);
return Parse(document);
}
/// <summary>
/// Parses the stream and returns the result.
/// </summary>
public IXmlDocument ParseDocument(Stream source)
{
var document = CreateDocument(source);
return Parse(document);
}
/// <summary>
/// Parses the string asynchronously with option to cancel.
/// </summary>
public Task<IXmlDocument> ParseDocumentAsync(String source, CancellationToken cancel)
{
var document = CreateDocument(source);
return ParseAsync(document, cancel);
}
/// <summary>
/// Parses the stream asynchronously with option to cancel.
/// </summary>
public Task<IXmlDocument> ParseDocumentAsync(Stream source, CancellationToken cancel)
{
var document = CreateDocument(source);
return ParseAsync(document, cancel);
}
async Task<IDocument> IXmlParser.ParseDocumentAsync(IDocument document, CancellationToken cancel)
{
var parser = CreateBuilder((Document)document);
InvokeEventListener(new XmlParseEvent(document, completed: false));
await parser.ParseAsync(_options, cancel).ConfigureAwait(false);
InvokeEventListener(new XmlParseEvent(document, completed: true));
return document;
}
#endregion
#region Helpers
private XmlDocument CreateDocument(String source)
{
var textSource = new TextSource(source);
return CreateDocument(textSource);
}
private XmlDocument CreateDocument(Stream source)
{
var textSource = new TextSource(source, _context.GetDefaultEncoding());
return CreateDocument(textSource);
}
private XmlDocument CreateDocument(TextSource textSource)
{
var document = new XmlDocument(_context, textSource);
return document;
}
private XmlDomBuilder CreateBuilder(Document document)
{
var parser = new XmlDomBuilder(document);
return parser;
}
private IXmlDocument Parse(XmlDocument document)
{
var parser = CreateBuilder(document);
InvokeEventListener(new XmlParseEvent(document, completed: false));
parser.Parse(_options);
InvokeEventListener(new XmlParseEvent(document, completed: true));
return document;
}
private async Task<IXmlDocument> ParseAsync(XmlDocument document, CancellationToken cancel)
{
var parser = CreateBuilder(document);
InvokeEventListener(new XmlParseEvent(document, completed: false));
await parser.ParseAsync(_options, cancel).ConfigureAwait(false);
InvokeEventListener(new XmlParseEvent(document, completed: true));
return document;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,39 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Dom;
using AngleSharp.Xml.Dom;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Extensions for the IXmlParser instances.
/// </summary>
public static class XmlParserExtensions
{
/// <summary>
/// Parses the string asynchronously.
/// </summary>
public static Task<IXmlDocument> ParseDocumentAsync(this IXmlParser parser, String source)
{
return parser.ParseDocumentAsync(source, CancellationToken.None);
}
/// <summary>
/// Parses the stream asynchronously.
/// </summary>
public static Task<IXmlDocument> ParseDocumentAsync(this IXmlParser parser, Stream source)
{
return parser.ParseDocumentAsync(source, CancellationToken.None);
}
/// <summary>
/// Populates the given document asynchronously.
/// </summary>
public static Task<IDocument> ParseDocumentAsync(this IXmlParser parser, IDocument document)
{
return parser.ParseDocumentAsync(document, CancellationToken.None);
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
namespace AngleSharp.Xml.Parser
{
using AngleSharp.Dom;
using AngleSharp.Text;
using System;
/// <summary>
/// Contains a number of options for the XML parser.
/// </summary>
public struct XmlParserOptions
{
/// <summary>
/// Gets or sets if errors should be surpressed. This way the document
/// will be parsed for sure, but may look weird.
/// </summary>
public Boolean IsSuppressingErrors
{
get;
set;
}
/// <summary>
/// Gets or sets the callback once a new element was created.
/// </summary>
public Action<IElement, TextPosition> OnCreated
{
get;
set;
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
namespace AngleSharp.Xml.Parser
{
/// <summary>
/// An enumation of all possible tokens.
/// </summary>
enum XmlTokenType : byte
{
/// <summary>
/// The DOCTYPE token.
/// </summary>
Doctype,
/// <summary>
/// The XML declaration.
/// </summary>
Declaration,
/// <summary>
/// The start tag token to mark open tags.
/// </summary>
StartTag,
/// <summary>
/// The end tag token to mark ending tags.
/// </summary>
EndTag,
/// <summary>
/// The comment tag to mark comments.
/// </summary>
Comment,
/// <summary>
/// The CData token for such regions.
/// </summary>
CData,
/// <summary>
/// The character token to mark a single character.
/// </summary>
Character,
/// <summary>
/// A charref token to mark character references.
/// </summary>
CharacterReference,
/// <summary>
/// A processing instruction token to mark such elements.
/// </summary>
ProcessingInstruction,
/// <summary>
/// The End-Of-File token to mark the end.
/// </summary>
EndOfFile
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,29 @@
namespace AngleSharp.Xml.Parser
{
/// <summary>
/// Possible insertation mode values.
/// </summary>
enum XmlTreeMode : byte
{
/// <summary>
/// The initial mode - waiting for the XML declaration.
/// </summary>
Initial,
/// <summary>
/// The prolog (before the doctype or any element).
/// </summary>
Prolog,
/// <summary>
/// The misc mode (e.g. between doctype and first element).
/// </summary>
Misc,
/// <summary>
/// The body (after the doctype or first element).
/// </summary>
Body,
/// <summary>
/// The misc mode (after root).
/// </summary>
After
}
}

Просмотреть файл

@ -0,0 +1,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("Copyright © AngleSharp, 2013-2019")]
[assembly: ComVisible(false)]
[assembly: InternalsVisibleToAttribute("AngleSharp.Xml.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010001adf274fa2b375134e8e4558d606f1a0f96f5cd0c6b99970f7cce9887477209d7c29f814e2508d8bd2526e99e8cd273bd1158a3984f1ea74830ec5329a77c6ff201a15edeb8b36ab046abd1bce211fe8dbb076d7d806f46b15bfda44def04ead0669971e96c5f666c9eda677f28824fff7aa90d32929ed91d529a7a41699893")]

Просмотреть файл

@ -0,0 +1,54 @@
namespace AngleSharp.Xml
{
using AngleSharp.Dom;
using AngleSharp.Io;
using AngleSharp.Svg.Dom;
using AngleSharp.Xml.Dom;
using AngleSharp.Xml.Parser;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// XML related extensions for the configuration.
/// </summary>
public static class XmlConfigurationExtensions
{
/// <summary>
/// Adds XML capabilities to the configuration.
/// </summary>
/// <param name="configuration">The configuration to extend.</param>
/// <returns>The new configuration.</returns>
public static IConfiguration WithXml(this IConfiguration configuration)
{
var documentFactory = configuration.Services.OfType<DefaultDocumentFactory>().FirstOrDefault();
if (documentFactory != null)
{
documentFactory.Register(MimeTypeNames.Xml, LoadXmlAsync);
documentFactory.Register(MimeTypeNames.ApplicationXml, LoadXmlAsync);
documentFactory.Register(MimeTypeNames.Svg, LoadSvgAsync);
}
return configuration.WithOnly<IXmlParser>(ctx => new XmlParser(ctx));
}
private static Task<IDocument> LoadXmlAsync(IBrowsingContext context, CreateDocumentOptions options, CancellationToken cancellationToken)
{
var parser = context.GetService<IXmlParser>();
var document = new XmlDocument(context, options.Source);
document.Setup(options.Response, options.ContentType, options.ImportAncestor);
context.NavigateTo(document);
return parser.ParseDocumentAsync(document, cancellationToken);
}
private static Task<IDocument> LoadSvgAsync(IBrowsingContext context, CreateDocumentOptions options, CancellationToken cancellationToken)
{
var parser = context.GetService<IXmlParser>();
var document = new SvgDocument(context, options.Source);
document.Setup(options.Response, options.ContentType, options.ImportAncestor);
context.NavigateTo(document);
return parser.ParseDocumentAsync(document, cancellationToken);
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
namespace AngleSharp.Xml
{
using AngleSharp.Dom;
using System;
using System.Collections.Generic;
/// <summary>
/// Represents the list of all Xml entities.
/// </summary>
public sealed class XmlEntityProvider : IEntityProvider
{
#region Fields
private readonly Dictionary<String, String> _entities = new Dictionary<String, String>
{
{ "amp;", "&" },
{ "lt;", "<" },
{ "gt;", ">" },
{ "apos;", "'" },
{ "quot;", "\"" }
};
#endregion
#region Instance
/// <summary>
/// Gets the instance to resolve entities.
/// </summary>
public static readonly IEntityProvider Resolver = new XmlEntityProvider();
#endregion
#region ctor
private XmlEntityProvider()
{
}
#endregion
#region Methods
/// <summary>
/// Gets a symbol specified by its entity name.
/// </summary>
/// <param name="name">The name of the entity in the XML code.</param>
/// <returns>The string with the symbol or null.</returns>
public String GetSymbol(String name)
{
var symbol = String.Empty;
if (!String.IsNullOrEmpty(name))
{
_entities.TryGetValue(name, out symbol);
}
return symbol;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,136 @@
namespace AngleSharp.Xml
{
using AngleSharp.Dom;
using AngleSharp.Text;
using System;
/// <summary>
/// Represents the standard XML markup formatter.
/// </summary>
public sealed class XmlMarkupFormatter : IMarkupFormatter
{
#region Instance
/// <summary>
/// An instance of the XmlMarkupFormatter.
/// </summary>
public static readonly IMarkupFormatter Instance = new XmlMarkupFormatter();
#endregion
#region Methods
String IMarkupFormatter.CloseTag(IElement element, Boolean selfClosing)
{
var prefix = element.Prefix;
var name = element.LocalName;
var tag = !String.IsNullOrEmpty(prefix) ? prefix + ":" + name : name;
return selfClosing ? String.Empty : String.Concat("</", tag, ">");
}
String IMarkupFormatter.Comment(IComment comment)
{
return String.Concat("<!--", comment.Data, "-->");
}
String IMarkupFormatter.Doctype(IDocumentType doctype)
{
var publicId = doctype.PublicIdentifier;
var systemId = doctype.SystemIdentifier;
var noExternalId = String.IsNullOrEmpty(publicId) && String.IsNullOrEmpty(systemId);
var externalId = noExternalId ? String.Empty : " " + (String.IsNullOrEmpty(publicId) ?
String.Concat("SYSTEM \"", systemId, "\"") :
String.Concat("PUBLIC \"", publicId, "\" \"", systemId, "\""));
return String.Concat("<!DOCTYPE ", doctype.Name, externalId, ">");
}
String IMarkupFormatter.OpenTag(IElement element, Boolean selfClosing)
{
var prefix = element.Prefix;
var temp = StringBuilderPool.Obtain();
temp.Append(Symbols.LessThan);
if (!String.IsNullOrEmpty(prefix))
{
temp.Append(prefix).Append(Symbols.Colon);
}
temp.Append(element.LocalName);
foreach (var attribute in element.Attributes)
{
temp.Append(" ").Append(Instance.Attribute(attribute));
}
if (selfClosing)
{
temp.Append(" /");
}
temp.Append(Symbols.GreaterThan);
return temp.ToPool();
}
String IMarkupFormatter.Processing(IProcessingInstruction processing)
{
var value = String.Concat(processing.Target, " ", processing.Data);
return String.Concat("<?", value, "?>");
}
String IMarkupFormatter.Text(ICharacterData text)
{
var content = text.Data;
return EscapeText(content);
}
String IMarkupFormatter.Attribute(IAttr attribute)
{
var value = attribute.Value;
var temp = StringBuilderPool.Obtain();
temp.Append(attribute.Name);
temp.Append(Symbols.Equality).Append(Symbols.DoubleQuote);
for (var i = 0; i < value.Length; i++)
{
switch (value[i])
{
case Symbols.Ampersand: temp.Append("&amp;"); break;
case Symbols.LessThan: temp.Append("&lt;"); break;
case Symbols.DoubleQuote: temp.Append("&quot;"); break;
default: temp.Append(value[i]); break;
}
}
return temp.Append(Symbols.DoubleQuote).ToPool();
}
#endregion
#region Helpers
/// <summary>
/// Escapes the given text by replacing special characters with their
/// XML entity (only applies to ampersands and opening angle brackets).
/// </summary>
/// <param name="content">The string to alter.</param>
/// <returns>The altered string.</returns>
public static String EscapeText(String content)
{
var temp = StringBuilderPool.Obtain();
for (var i = 0; i < content.Length; i++)
{
switch (content[i])
{
case Symbols.Ampersand: temp.Append("&amp;"); break;
case Symbols.LessThan: temp.Append("&lt;"); break;
default: temp.Append(content[i]); break;
}
}
return temp.ToPool();
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,7 @@
<Project>
<PropertyGroup>
<Description>Adds a powerful XML and DTD parser to AngleSharp.</Description>
<Product>AngleSharp.Xml</Product>
<Version>0.11.0</Version>
</PropertyGroup>
</Project>