Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
xmloxide — 순수 Rust로 작성된 libxml2 재구현 | Kitploit
도구/GitHubGitHub/jonwiggins/xmloxide
Static AnalysisVulnerability AnalysisCode AnalysisFuzzingBinary AnalysisLearning & EducationCurated ResourcesLabs & Practice
GitHubjonwiggins/xmloxide

xmloxide

순수 Rust로 작성된 libxml2 재구현

저장소 보기
848752개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
# xmloxide

[![CI](https://github.com/jonwiggins/xmloxide/actions/workflows/ci.yml/badge.svg)](https://github.com/jonwiggins/xmloxide/actions/workflows/ci.yml)
[![crates.io](https://img.shields.io/crates/v/xmloxide.svg)](https://crates.io/crates/xmloxide)
[![docs.rs](https://docs.rs/xmloxide/badge.svg)](https://docs.rs/xmloxide)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![MSRV](https://img.shields.io/badge/MSRV-1.81-blue.svg)](https://www.rust-lang.org)

libxml2의 순수 Rust 재구현 — 오픈 소스 세계에서 사실상 표준인 XML/HTML 파싱 라이브러리입니다.

libxml2는 2025년 12월에 알려진 보안 문제로 인해 공식적으로 유지보수가 중단되었습니다. xmloxide는 동일한 적합성 테스트 스위트를 통과하는 메모리 안전하고 고성능인 대체제를 목표로 합니다.

## Features

- **메모리 안전** — 공개 API에 `unsafe`가 전혀 없는 아레나 기반 트리
- **규격 준수** — W3C XML 적합성 테스트 스위트 100% 통과 (1727/1727 해당 테스트)
- **오류 복구** — libxml2처럼 잘못된 XML도 파싱하여 사용 가능한 트리 생성
- **다중 파싱 API** — DOM 트리, SAX2 스트리밍, XmlReader 풀, 푸시/증분
- **HTML 파서** — 자동 닫힘 및 void 요소를 지원하는 오류 허용 HTML 4.01 파싱
- **WHATWG HTML5 파서** — 전체 [HTML Living Standard](https://html.spec.whatwg.org/) 토크나이저 및 트리 빌더 (8810/8810 html5lib-tests 통과)
- **HTML5 스트리밍** — DOM 트리를 구축하지 않고 토크나이저를 감싸는 HTML5용 SAX 유사 콜백 API (`html5::sax`)
- **CSS 선택자** — 친숙한 CSS 구문(`css::select`)으로 요소 쿼리, 결합자, 의사 클래스 및 빠른 `#id` 조회 포함
- **XPath 1.0+** — 모든 XPath 1.0 핵심 함수와 주요 XPath 2.0 함수(`matches()`, `replace()`, `tokenize()`, `upper-case()`, `lower-case()`, `abs()`, `min()`, `max()` 등)를 포함한 완전한 표현식 파서 및 평가기
- **검증** — DTD, RelaxNG, XML Schema (XSD), ISO Schematron (ISO/IEC 19757-3) 검증
- **Serde 통합** — Rust 타입과 XML (역)직렬화를 위한 선택적 `serde` 기능
- **비동기 파싱** — `tokio::io::AsyncRead` 소스에서 파싱을 위한 선택적 `async` 기능
- **정식 XML** — C14N 1.0 및 Exclusive C14N 직렬화
- **XInclude** — 문서 포함 처리
- **XML 카탈로그** — URI 해석을 위한 OASIS XML 카탈로그
- **`xmllint` CLI** — XML 파싱, 검증 및 쿼리를 위한 명령줄 도구
- **가능한 Zero-copy** — 빠른 비교를 위한 문자열 인터닝
- **전역 상태 없음** — 각 `Document`는 독립적이며 `Send + Sync`
- **C/C++ FFI** — C/C++ 프로젝트에 포함하기 위한 전체 C API 및 헤더 파일 (`include/xmloxide.h`)
- **최소 의존성** — `encoding_rs`만 사용 (라이브러리에는 다른 의존성이 없으며, `clap`은 CLI 전용)

## Quick Start

```rust
use xmloxide::Document;

let doc = Document::parse_str("<root><child>Hello</child></root>").unwrap();
let root = doc.root_element().unwrap();
assert_eq!(doc.node_name(root), Some("root"));
assert_eq!(doc.text_content(root), "Hello");
```

### Serialization

```rust
use xmloxide::Document;
use xmloxide::serial::serialize;

let doc = Document::parse_str("<root><child>Hello</child></root>").unwrap();
let xml = serialize(&doc);
assert_eq!(xml, "<root><child>Hello</child></root>");
```

### XPath Queries

```rust
use xmloxide::Document;
use xmloxide::xpath::{evaluate, XPathValue};

let doc = Document::parse_str("<library><book><title>Rust</title></book></library>").unwrap();
let root = doc.root_element().unwrap();
let result = evaluate(&doc, root, "count(book)").unwrap();
assert_eq!(result.to_number(), 1.0);
```

### SAX2 Streaming

```rust
use xmloxide::sax::{parse_sax, SaxHandler, DefaultHandler};
use xmloxide::parser::ParseOptions;

struct MyHandler;
impl SaxHandler for MyHandler {
    fn start_element(&mut self, name: &str, _: Option<&str>, _: Option<&str>,
                     _: &[(String, String, Option<String>, Option<String>)]) {
        println!("Element: {name}");
    }
}

parse_sax("<root><child/></root>", &ParseOptions::default(), &mut MyHandler).unwrap();
```

### HTML Parsing

```rust
use xmloxide::html::parse_html;

let doc = parse_html("<p>Hello <br> World").unwrap();
let root = doc.root_element().unwrap();
assert_eq!(doc.node_name(root), Some("html"));
```

### CSS Selectors

```rust
use xmloxide::css::select;
use xmloxide::Document;

let doc = Document::parse_str(r#"<div><p class="intro">Hello</p><p>World</p></div>"#).unwrap();
let root = doc.root_element().unwrap();
let intros = select(&doc, root, "p.intro").unwrap();
assert_eq!(intros.len(), 1);
assert_eq!(doc.text_content(intros[0]), "Hello");
```

### HTML5 Parsing (WHATWG)

```rust
use xmloxide::html5::parse_html5;

let doc = parse_html5("<p>Hello <b>world</b>").unwrap();
let root = doc.root_element().unwrap();
assert_eq!(doc.node_name(root), Some("html"));
```

Fragment parsing (the algorithm behind `innerHTML`) is also supported:

```rust
use xmloxide::html5::{parse_html5_with_options, Html5ParseOptions};

let opts = Html5ParseOptions {
    scripting: false,
    fragment_context: Some("body".to_string()),
};
let doc = parse_html5_with_options("<p>fragment</p>", &opts).unwrap();
```

### HTML5 Streaming (SAX-like)

```rust
use xmloxide::html5::sax::{Html5SaxHandler, parse_html5_sax};

struct LinkExtractor { hrefs: Vec<String> }
impl Html5SaxHandler for LinkExtractor {
    fn start_element(&mut self, name: &str, attrs: &[(String, String)], _sc: bool) {
        if name == "a" {
            if let Some((_, href)) = attrs.iter().find(|(n, _)| n == "href") {
                self.hrefs.push(href.clone());
            }
        }
    }
}

let mut handler = LinkExtractor { hrefs: Vec::new() };
parse_html5_sax(r#"<a href="https://github.com/jonwiggins/xmloxide/blob/main/page">Link</a>"#, &mut handler);
assert_eq!(handler.hrefs, vec!["/page"]);
```

### Error Recovery

```rust
use xmloxide::parser::{parse_str_with_options, ParseOptions};

let opts = ParseOptions::default().recover(true);
let doc = parse_str_with_options("<root><unclosed>", &opts).unwrap();
for diag in &doc.diagnostics {
    eprintln!("{}", diag);
}
```

## CLI Tool

```sh
# Parse and pretty-print
xmllint --format document.xml

# Validate against a schema
xmllint --schema schema.xsd document.xml
xmllint --relaxng schema.rng document.xml
xmllint --schematron schema.sch document.xml
xmllint --dtdvalid schema.dtd document.xml

# XPath query
xmllint --xpath "//title" document.xml

# Canonical XML
xmllint --c14n document.xml

# Parse HTML
xmllint --html page.html
```

## Module Overview

| Module | Description |
|--------|-------------|
| `tree` | 아레나 기반 DOM 트리 (`Document`, `NodeId`, `NodeKind`) |
| `parser` | 오류 복구를 지원하는 XML 1.0 재귀 하향 파서 |
| `parser::push` | 청크 입력을 위한 푸시/증분 파서 |
| `html` | 오류 허용 HTML 4.01 파서 |
| `html5` | WHATWG HTML Living Standard 파서 (토크나이저 + 트리 빌더) |
| `html5::sax` | HTML5용 스트리밍 SAX 유사 API (DOM 트리 구축 없음) |
| `css` | 문서 트리 쿼리를 위한 CSS 선택자 엔진 |
| `sax` | SAX2 스트리밍 이벤트 기반 파서 |
| `reader` | XmlReader 풀 기반 파싱 API |
| `serial` | XML, HTML 및 HTML5 직렬화기, Canonical XML (C14N) 포함 |
| `xpath` | XPath 1.0+ 표현식 파서 및 평가기 |
| `validation::dtd` | DTD 파싱 및 검증 |
| `validation::relaxng` | RelaxNG 스키마 검증 |
| `validation::xsd` | XML Schema (XSD) 검증 |
| `validation::schematron` | ISO Schematron 규칙 기반 검증 |
| `serde_xml` | Serde XML (역)직렬화 (선택적 `serde` 기능) |
| `async_xml` | `tokio::io::AsyncRead`를 통한 비동기 파싱 (선택적 `async` 기능) |
| `xinclude` | XInclude 1.0 문서 포함 |
| `catalog` | URI 해석을 위한 OASIS XML 카탈로그 |
| `encoding` | 문자 인코딩 감지 및 트랜스코딩 |
| `ffi` | C/C++ FFI 바인딩 (`include/xmloxide.h`) |

## Performance

파싱 처리량은 libxml2와 경쟁력이 있습니다 — 대부분의 문서에서 3-4% 이내, SVG의 경우 **12% 더 빠릅니다**. 직렬화는 아레나 기반 트리 설계 덕분에 **1.5-2.4배 더 빠릅니다**. XPath는 모든 벤치마크에서 **1.1-2.7배 더 빠릅니다**.

**Parsing:**

| Document | Size | xmloxide | libxml2 | Result |
|----------|------|----------|---------|--------|
| Atom 피드 | 4.9 KB | 26.7 µs (176 MiB/s) | 25.5 µs (184 MiB/s) | 약 4% 느림 |
| SVG 도면 | 6.3 KB | 58.5 µs (103 MiB/s) | 65.6 µs (92 MiB/s) | **12% 더 빠름** |
| Maven POM | 11.5 KB | 76.9 µs (142 MiB/s) | 74.2 µs (148 MiB/s) | 약 4% 느림 |
| XHTML 페이지 | 10.2 KB | 69.5 µs (139 MiB/s) | 61.5 µs (157 MiB/s) | 약 13% 느림 |
| 대용량 (374 KB) | 374 KB | 2.15 ms (169 MiB/s) | 2.08 ms (175 MiB/s) | 약 3% 느림 |

**Serialization:**

| Document | Size | xmloxide | libxml2 | Result |
|----------|------|----------|---------|--------|
| Atom 피드 | 4.9 KB | 11.3 µs | 17.5 µs | **1.5배 더 빠름** |
| Maven POM | 11.5 KB | 20.1 µs | 47.5 µs | **2.4배 더 빠름** |
| 대용량 (374 KB) | 374 KB | 614 µs | 1397 µs | **2.3배 더 빠름** |

**XPath:**

| 표현식 | xmloxide | libxml2 | Result |
|------------|----------|---------|--------|
| 단순 경로 (`//entry/title`) | 1.51 µs | 1.63 µs | **8% 더 빠름** |
| 속성 조건 (`//book[@id]`) | 5.91 µs | 15.99 µs | **2.7배 더 빠름** |
| `count()` 함수 | 1.09 µs | 1.67 µs | **1.5배 더 빠름** |
| `string()` 함수 | 1.32 µs | 1.77 µs | **1.3배 더 빠름** |

주요 최적화: 빠른 직렬화를 위한 아레나 기반 트리, 문자 검증을 위한 바이트 수준 사전 검사, 대량 텍스트 스캔, 이름 파싱을 위한 ASCII 고속 경로, 제로 카피 요소 이름 분할, 인라인 엔터티 해석, XPath `//` 단계 융합 및 융합 축 확장, 인라인 트리 접근자, 자식/하위 축에 대한 이름 테스트 고속 경로.

```sh
# Run benchmarks (requires libxml2 system library)
cargo bench --features bench-libxml2 --bench comparison_bench
```

## Testing

- **1078개의 단위 테스트** — 모든 모듈
- **138개의 FFI 테스트** — 전체 C API 표면 (SAX, Schematron 및 CSS 포함)
- **libxml2 호환성 테스트 스위트** — 119/119 테스트 통과 (100%) — XML 파싱, 네임스페이스, 오류 감지 및 HTML 파싱 포함
- **W3C XML 적합성 테스트 스위트** — 1727/1727 해당 테스트 통과 (100%)
- **html5lib-tests** — 7032/7032 토크나이저 테스트 + 1778/1778 트리 구성 테스트 (100%)
- **통합 테스트** — 실제 XML/HTML 문서, 엣지 케이스 및 오류 복구 포함

```sh
cargo test --all-features
```

## C/C++ FFI

xmloxide는 C/C++ 프로젝트(예: Chromium, 게임 엔진 또는 현재 libxml2를 사용하는 모든 코드베이스)에 포함할 수 있는 C 호환 API를 제공합니다.

```sh
# Build shared + static libraries (uses the included Makefile)
make

# Or build individually:
make shared   # .so / .dylib / .dll
make static   # .a / .lib

# Build and run the C example
make example
```

```c
#include "xmloxide.h"

xmloxide_document *doc = xmloxide_parse_str("<root>Hello</root>");
uint32_t root = xmloxide_doc_root_element(doc);
char *name = xmloxide_node_name(doc, root);   // "root"
char *text = xmloxide_node_text_content(doc, root); // "Hello"

xmloxide_free_string(name);
xmloxide_free_string(text);
xmloxide_free_doc(doc);
```

전체 API(트리 탐색 및 변형, XPath 평가, 직렬화(일반 및 정리 인쇄), HTML/HTML5 파싱, DTD/RelaxNG/XSD/Schematron 검증, C14N, SAX 스트리밍, XmlReader, 푸시 파서 및 XML 카탈로그 포함)는 [`include/xmloxide.h`](https://github.com/jonwiggins/xmloxide/blob/main/include/xmloxide.h)에 선언되어 있습니다.

## Migrating from libxml2

| libxml2 | xmloxide (Rust) | xmloxide (C FFI) |
|---------|----------------|------------------|
| `xmlReadMemory` | `Document::parse_str` | `xmloxide_parse_str` |
| `xmlReadFile` | `Document::parse_file` | `xmloxide_parse_file` |
| `xmlParseDoc` | `Document::parse_bytes` | `xmloxide_parse_bytes` |
| `htmlReadMemory` | `html::parse_html` | `xmloxide_parse_html` |
| (HTML5 parsing) | `html5::parse_html5` | — |
| (HTML5 fragment / innerHTML) | `html5::parse_html5_with_options` | — |
| (HTML5 streaming) | `html5::sax::parse_html5_sax` | — |
| (CSS selectors / `querySelector`) | `css::select` | — |
| `xmlFreeDoc` | (drop `Document`) | `xmloxide_free_doc` |
| `xmlDocGetRootElement` | `doc.root_element()` | `xmloxide_doc_root_element` |
| `xmlNodeGetContent` | `doc.text_content(id)` | `xmloxide_node_text_content` |
| `xmlNodeSetContent` | `doc.set_text_content(id, s)` | `xmloxide_set_text_content` |
| `xmlGetProp` | `doc.attribute(id, name)` | `xmloxide_node_attribute` |
| `xmlSetProp` | `doc.set_attribute(...)` | `xmloxide_set_attribute` |
| `xmlNewNode` | `doc.create_node(...)` | `xmloxide_create_element` |
| `xmlNewText` | `doc.create_node(Text{..})` | `xmloxide_create_text` |
| `xmlAddChild` | `doc.append_child(p, c)` | `xmloxide_append_child` |
| `xmlAddPrevSibling` | `doc.insert_before(ref, c)` | `xmloxide_insert_before` |
| `xmlUnlinkNode` | `doc.remove_node(id)` | `xmloxide_remove_node` |
| `xmlCopyNode` | `doc.clone_node(id, deep)` | `xmloxide_clone_node` |
| `xmlGetID` | `doc.element_by_id(s)` | `xmloxide_element_by_id` |
| `xmlDocDumpMemory` | `serial::serialize(&doc)` | `xmloxide_serialize` |
| `xmlDocDumpFormatMemory` | `serial::serialize_with_options` | `xmloxide_serialize_pretty` |
| `htmlDocDumpMemory` | `serial::html::serialize_html` | `xmloxide_serialize_html` |
| `xmlC14NDocDumpMemory` | `serial::c14n::canonicalize` | `xmloxide_canonicalize` |
| `xmlXPathEvalExpression` | `xpath::evaluate` | `xmloxide_xpath_eval` |
| `xmlValidateDtd` | `validation::dtd::validate` | `xmloxide_validate_dtd` |
| `xmlRelaxNGValidateDoc` | `validation::relaxng::validate` | `xmloxide_validate_relaxng` |
| `xmlSchemaValidateDoc` | `validation::xsd::validate_xsd` | `xmloxide_validate_xsd` |
| (Schematron validation) | `validation::schematron::validate_schematron` | `xmloxide_validate_schematron` |
| `xmlXIncludeProcess` | `xinclude::process_xincludes` | `xmloxide_process_xincludes` |
| `xmlLoadCatalog` | `Catalog::parse` | `xmloxide_parse_catalog` |
| `xmlSAX2...` callbacks | `sax::SaxHandler` trait | `xmloxide_sax_parse` |
| `xmlTextReaderRead` | `reader::XmlReader` | `xmloxide_reader_read` |
| `xmlCreatePushParserCtxt` | `parser::PushParser` | `xmloxide_push_parser_new` |
| `xmlParseChunk` | `PushParser::push` | `xmloxide_push_parser_push` |

**Thread safety:** Unlike libxml2, xmloxide has no global state. Each `Document` is self-contained and `Send + Sync`. The FFI layer uses thread-local storage for the last error message — each thread has its own error state. No initialization or cleanup functions are needed.

**스레드 안전성:** libxml2와 달리 xmloxide에는 전역 상태가 없습니다. 각 `Document`는 독립적이며 `Send + Sync`입니다. FFI 계층은 마지막 오류 메시지에 대해 스레드 로컬 저장소를 사용합니다. 각 스레드는 자체 오류 상태를 가집니다. 초기화 또는 정리 함수가 필요하지 않습니다.

## Fuzzing

xmloxide includes fuzz targets for security testing:

```sh
# Install cargo-fuzz (requires nightly)
cargo install cargo-fuzz

# Run a fuzz target
cargo +nightly fuzz run fuzz_xml_parse
cargo +nightly fuzz run fuzz_html_parse
cargo +nightly fuzz run fuzz_html5_parse
cargo +nightly fuzz run fuzz_html5_fragment
cargo +nightly fuzz run fuzz_xpath
cargo +nightly fuzz run fuzz_roundtrip
cargo +nightly fuzz run fuzz_sax
cargo +nightly fuzz run fuzz_reader
cargo +nightly fuzz run fuzz_push
cargo +nightly fuzz run fuzz_validation
cargo +nightly fuzz run fuzz_schematron
```

xmloxide는 보안 테스트를 위한 퍼징 타겟을 포함합니다.

## Building

```sh
cargo build
cargo test
cargo clippy --all-targets --all-features -- -D warnings
cargo bench
```

Minimum supported Rust version: **1.81**

최소 지원 Rust 버전: **1.81**

## Limitations

- **XML 1.1 미지원** — xmloxide는 XML 1.0(5판)만 구현합니다. XML 1.1은 거의 사용되지 않으며 계획에 없습니다.
- **XSLT 미지원** — XSLT는 별도 사양(libxslt)으로 범위를 벗어납니다.
- **HTML 파서** — HTML 4.01 파서(libxml2의 동작과 일치)와 전체 WHATWG HTML5 파서가 모두 제공됩니다. HTML5 파서는 html5lib-tests를 100% 통과합니다.
- **푸시 파서는 내부적으로 버퍼링** — 푸시/증분 파서 API(`PushParser`)는 현재 모든 푸시된 데이터를 버퍼링하고 `finish()`에서 전체 파싱을 수행합니다. libxml2의 `xmlParseChunk`처럼 진정한 스트리밍 방식이 아닙니다. 대용량 문서 처리를 위한 메모리 제약이 있는 경우 SAX 스트리밍(XML용 `parse_sax`, HTML5용 `html5::sax::parse_html5_sax`)을 대안으로 사용할 수 있습니다.
- **XPath `namespace::` 축** — `namespace::` 축은 범위 내 네임스페이스가 일치할 때 요소 노드를 반환합니다(별도의 네임스페이스 노드를 구체화하지 않음). 이는 속성 축과 동일한 패턴을 따릅니다.

## Contributing

기여에 대해서는 [CONTRIBUTING.md](https://github.com/jonwiggins/xmloxide/blob/main/CONTRIBUTING.md)를 참조하세요.

## Changelog

버전 기록은 [CHANGELOG.md](https://github.com/jonwiggins/xmloxide/blob/main/CHANGELOG.md)를 참조하세요.

## License

MIT
도구 다운로드