├── .github └── workflows │ ├── linux.yml │ ├── macos.yml │ └── windows.yml ├── .gitignore ├── Build.pm6 ├── Changes ├── LICENSE ├── META6.json ├── Makefile.in ├── README.md ├── _config.yml ├── appveyor.yml ├── dist.ini ├── docs ├── Attr.md ├── Attr │ └── Map.md ├── CDATA.md ├── Comment.md ├── Config.md ├── DOM.md ├── Dict.md ├── Document.md ├── DocumentFragment.md ├── Dtd.md ├── Dtd │ ├── AttrDecl.md │ ├── ElementContent.md │ ├── ElementDecl.md │ ├── Entity.md │ └── Notation.md ├── Element.md ├── EntityRef.md ├── Enums.md ├── ErrorHandling.md ├── HashMap.md ├── InputCallback.md ├── Item.md ├── Namespace.md ├── Node.md ├── Node │ ├── List.md │ └── Set.md ├── PI.md ├── Parser.md ├── Pattern.md ├── PushParser.md ├── Raw.md ├── Reader.md ├── RegExp.md ├── RelaxNG.md ├── SAX │ ├── Builder.md │ └── Handler │ │ ├── SAX2.md │ │ └── XML.md ├── Schema.md ├── Text.md ├── Threads.md ├── XInclude │ └── Context.md ├── XPath │ ├── Context.md │ └── Expression.md ├── _CharacterData.md ├── _config.yml └── index.md ├── etc ├── benchmark.raku ├── libxml2-api.xml └── resolve-links.raku ├── lib ├── LibXML.rakumod └── LibXML │ ├── Attr.rakumod │ ├── Attr │ └── Map.rakumod │ ├── CDATA.rakumod │ ├── Comment.rakumod │ ├── Config.rakumod │ ├── DOM.pod6 │ ├── Dict.rakumod │ ├── Document.rakumod │ ├── DocumentFragment.rakumod │ ├── Dtd.rakumod │ ├── Dtd │ ├── AttrDecl.rakumod │ ├── ElementContent.rakumod │ ├── ElementDecl.rakumod │ ├── Entity.rakumod │ └── Notation.rakumod │ ├── Element.rakumod │ ├── EntityRef.rakumod │ ├── Enums.rakumod │ ├── ErrorHandling.rakumod │ ├── HashMap.rakumod │ ├── InputCallback.rakumod │ ├── Item.rakumod │ ├── Namespace.rakumod │ ├── Node.rakumod │ ├── Node │ ├── List.rakumod │ └── Set.rakumod │ ├── PI.rakumod │ ├── Parser.rakumod │ ├── Parser │ └── Context.rakumod │ ├── Pattern.rakumod │ ├── PushParser.rakumod │ ├── Raw.rakumod │ ├── Raw │ ├── DOM │ │ ├── Attr.rakumod │ │ ├── Document.rakumod │ │ ├── Element.rakumod │ │ └── Node.rakumod │ ├── Defs.rakumod │ ├── Dict.rakumod │ ├── HashTable.rakumod │ ├── RelaxNG.rakumod │ ├── Schema.rakumod │ └── TextReader.rakumod │ ├── Reader.rakumod │ ├── RegExp.rakumod │ ├── RelaxNG.rakumod │ ├── SAX.rakumod │ ├── SAX │ ├── Builder.rakumod │ ├── Handler.rakumod │ └── Handler │ │ ├── SAX2.rakumod │ │ ├── SAX2 │ │ └── Locator.rakumod │ │ └── XML.rakumod │ ├── Schema.rakumod │ ├── Text.rakumod │ ├── Threads.pod6 │ ├── Types.rakumod │ ├── Utils.rakumod │ ├── X.rakumod │ ├── XInclude │ └── Context.rakumod │ ├── XPath │ ├── Context.rakumod │ ├── Expression.rakumod │ └── Object.rakumod │ ├── _CharacterData.rakumod │ ├── _Collection.rakumod │ ├── _Configurable.rakumod │ ├── _DomNode.rakumod │ ├── _Options.rakumod │ ├── _ParentNode.rakumod │ ├── _Rawish.rakumod │ └── _Validator.rakumod ├── resources └── libraries │ ├── README.windows │ ├── liblibxml2.dylib │ ├── liblibxml2.so │ ├── libxml2.dll │ └── xml6.dll ├── samples ├── JBR-ALLENtrees.htm ├── ProductCatalog.dtd ├── article.xml ├── article_bad.xml ├── article_external_bad.xml ├── article_internal_bad.xml ├── bad.dtd ├── bad.xml ├── catalog.xml ├── cdata.xml ├── complex │ ├── complex.dtd │ ├── complex.xml │ ├── complex2.xml │ └── dtd │ │ ├── f.dtd │ │ └── g.dtd ├── dromeds.xml ├── dtd.xml ├── enc2_latin2.html ├── enc_latin2.html ├── ext_ent.dtd ├── ns.xml ├── test.dtd ├── test.html ├── test.xml ├── test2.xml ├── test3.xml ├── test4.xml ├── utf-16-1.html ├── utf-16-2.html ├── utf-16-2.xml ├── xmllibxmldocs.raku └── xmlns │ ├── badguy.xml │ └── goodguy.xml ├── sparrow.yaml ├── src ├── dom.c ├── dom.h ├── domXPath.c ├── domXPath.h ├── xml6.h ├── xml6_config.c ├── xml6_config.h ├── xml6_doc.c ├── xml6_doc.h ├── xml6_entity.c ├── xml6_entity.h ├── xml6_entity.rakumod ├── xml6_error.c ├── xml6_error.h ├── xml6_gbl.c ├── xml6_gbl.h ├── xml6_hash.c ├── xml6_hash.h ├── xml6_input.c ├── xml6_input.h ├── xml6_node.c ├── xml6_node.h ├── xml6_notation.c ├── xml6_notation.h ├── xml6_ns.c ├── xml6_ns.h ├── xml6_parser_ctx.c ├── xml6_parser_ctx.h ├── xml6_reader.c ├── xml6_reader.h ├── xml6_ref.c ├── xml6_ref.h ├── xml6_sax.c ├── xml6_sax.h ├── xml6_xpath.c └── xml6_xpath.h ├── t ├── 000sanity.t ├── 00ast.t ├── 00config.t ├── 00dict.t ├── 00dom-w3c.t ├── 00dom.t ├── 00dtd-decls.t ├── 00dtd.t ├── 00errors.t ├── 00hash-object.t ├── 00hash-type.t ├── 00input-callback.t ├── 00native.t ├── 00query-selectors.t ├── 00sax-coverage.t ├── 00sax.t ├── 00subclass.t ├── 00threads.t ├── 00with-cache.t ├── 00xpath-object.t ├── 01basic.t ├── 02parse.t ├── 03doc.t ├── 04node.t ├── 05text.t ├── 06elements.t ├── 07dtd.t ├── 08findnodes.t ├── 09xpath.t ├── 10ns.t ├── 12html.t ├── 13dtd.t ├── 14sax.t ├── 15nodelist.t ├── 16docnodes.t ├── 17callbacks.t ├── 18docfree.t ├── 19encoding.t ├── 20extras.t ├── 21catalog.t ├── 23rawfunctions.t ├── 24c14n.t ├── 25relaxng.t ├── 26schema.t ├── 27input_callbacks_simple.t ├── 28input_callbacks_multiple.t ├── 29id.t ├── 30keep_blanks.t ├── 30xpathcontext.t ├── 31xpc_functions.t ├── 32xpc_variables.t ├── 35huge_mode.t ├── 40reader.t ├── 40reader_mem_error.t ├── 41xinclude.t ├── 42common.t ├── 43options.t ├── 44extent.t ├── 45regex.t ├── 46err_column.t ├── 47load_xml_callbacks.t ├── 48importing_nodes_IDs.t ├── 49global_extent.t ├── 60error_prev_chain.t ├── 61error.t ├── 90threads.t ├── 91unique_key.t ├── 99doc-examples.t ├── META6.json ├── data │ └── chinese.xml ├── issue#025.t ├── issue#095.t └── lib │ ├── Collector.rakumod │ ├── Counter.rakumod │ └── Stacker.rakumod ├── test ├── compression │ └── test.xml.gz ├── dtd │ ├── namespaces.xml │ ├── note-external-dtd.xml │ ├── note-internal-dtd.xml │ ├── note-no-dtd.xml │ ├── note.dtd │ ├── parameter-entities.dtd │ └── parameter-entities.xml ├── empty.txt ├── relaxng │ ├── badschema.rng │ ├── demo.rng │ ├── demo.xml │ ├── demo2.rng │ ├── demo3.rng │ ├── demo4.rng │ ├── invaliddemo.xml │ └── schema.rng ├── schema │ ├── badschema.xsd │ ├── demo.xml │ ├── invaliddemo.xml │ ├── net.xsd │ └── schema.xsd ├── textReader │ ├── SR2006_countries_config.dtd │ └── countries.xml └── xinclude │ ├── entity.txt │ ├── test.xml │ └── xinclude.xml └── xt ├── release ├── memory.t └── version.t └── xpath ├── 01_simple_basic_find.t ├── 02_descendant_find.t ├── 03_start_find.t ├── 04_pos_find.t ├── 05_attributes_find.t ├── 06_attributes_val_find.t ├── 07_count_find.t ├── 08_name_find.t ├── 09_string_length_find.t ├── 09_string_length_predicate_find.t ├── 10_pipe_find.t ├── 11_axis_child_find.t ├── 12_axis_descendant.t ├── 13_axis_parent.t ├── 14_axis_ancestor.t ├── 15_axis_following_sibling.t ├── 16_axis_preceding-sibling.t ├── 17_axis_following.t ├── 18_axis_preceding.t ├── 19_axis_descendant_or_self.t ├── 20_axis_ancestor_or_self.t ├── 21_all_nodes.t ├── 22_name_select.t ├── 23_much_more_function_and_expressions.t ├── 24_namespaces.t ├── 26_predicate.t ├── 28_ancestor2.t ├── 29_desc_with_predicate.t ├── 30_lang.t ├── 31_dots.t ├── 35_namespace_uri.t ├── 36_substring.t ├── 37_concat.t ├── 38_starts_with.t ├── 39_contains.t ├── 40_substring_before.t ├── 41_substring_after.t ├── 43_op_div.t ├── 44_test_compare.t ├── 46_context.t ├── 48_translate.t ├── 50_issue_9.t └── README /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | tags-ignore: 8 | - '*' 9 | pull_request: 10 | 11 | jobs: 12 | raku: 13 | strategy: 14 | matrix: 15 | os: 16 | - ubuntu-latest 17 | raku-version: 18 | - 'latest' 19 | - '2022.02' 20 | runs-on: ${{ matrix.os }} 21 | steps: 22 | - uses: actions/checkout@v2 23 | - uses: Raku/setup-raku@v1 24 | with: 25 | raku-version: ${{ matrix.raku-version }} 26 | - name: Linux specific setup 27 | run: sudo apt-get install -y libxml2-dev 28 | - name: Install Dependencies 29 | run: | 30 | zef install --/test LibraryMake 31 | zef install App::Prove6 32 | zef install --deps-only . 33 | zef build . 34 | - name: Run Tests 35 | run: prove6 -I . t 36 | -------------------------------------------------------------------------------- /.github/workflows/macos.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | tags-ignore: 8 | - '*' 9 | pull_request: 10 | 11 | jobs: 12 | raku: 13 | strategy: 14 | matrix: 15 | os: 16 | - macOS-latest 17 | raku-version: 18 | - 'latest' 19 | - '2022.02' 20 | runs-on: ${{ matrix.os }} 21 | steps: 22 | - uses: actions/checkout@v2 23 | - uses: Raku/setup-raku@v1 24 | with: 25 | raku-version: ${{ matrix.raku-version }} 26 | - name: macOS specific setup 27 | run: | 28 | brew update 29 | brew install libxml2 30 | - name: Install Dependencies 31 | run: | 32 | zef install --/test LibraryMake 33 | zef install App::Prove6 34 | zef install --deps-only . 35 | zef build . 36 | - name: Run Tests 37 | run: prove6 -I . t 38 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | tags-ignore: 8 | - '*' 9 | pull_request: 10 | 11 | jobs: 12 | raku: 13 | strategy: 14 | matrix: 15 | os: 16 | - windows-2019 17 | - windows-latest 18 | raku-version: 19 | - 'latest' 20 | - '2022.02' 21 | runs-on: ${{ matrix.os }} 22 | steps: 23 | - uses: actions/checkout@v2 24 | - uses: Raku/setup-raku@v1 25 | with: 26 | raku-version: ${{ matrix.raku-version }} 27 | - name: Install Dependencies 28 | run: | 29 | zef install --/test LibraryMake 30 | zef install App::Prove6 31 | zef install --deps-only . 32 | zef build . 33 | - name: Run Tests 34 | run: prove6 -I . t 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .* 3 | *.o 4 | *.obj 5 | Makefile 6 | blib/ 7 | README.md 8 | *.gz 9 | resources 10 | LibXML-* 11 | .gitignore 12 | samples/testrun.xml 13 | *.iml 14 | -------------------------------------------------------------------------------- /Build.pm6: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env perl6 2 | #Note `zef build .` will run this script 3 | use v6; 4 | 5 | class Build { 6 | need LibraryMake; 7 | # adapted from deprecated Native::Resources 8 | 9 | #| Sets up a C and runs C. C<$folder> should be 10 | #| C<"$folder/resources/lib"> and C<$libname> should be the name of the library 11 | #| without any prefixes or extensions. 12 | sub make(Str $folder, Str $destfolder, IO() :$libname!, Str :$I) { 13 | my %vars = LibraryMake::get-vars($destfolder); 14 | %vars = ~ $*VM.platform-library-name($libname); 15 | if Rakudo::Internals.IS-WIN { 16 | unless $I { 17 | note "Using prebuilt DLLs on Windows"; 18 | return True; 19 | } 20 | 21 | %vars = "-I$I"; 22 | %vars = '-lxml2'; 23 | %vars = 'make'; 24 | %vars = 'gcc'; 25 | %vars = '-fPIC -O3 -DNDEBUG --std=gnu99 -Wextra -Wall'; 26 | %vars = 'gcc'; 27 | %vars = '-shared'; 28 | %vars = "-fPIC -O3 -Lresources/libraries"; 29 | %vars = '-o '; 30 | %vars = '-o '; 31 | } 32 | else { 33 | %vars = chomp(qx{xml2-config --libs 2>/dev/null} || '-lxml2'); 34 | %vars = $I 35 | ?? "-I$I" 36 | !! chomp(qx{xml2-config --cflags 2>/dev/null} || '-I/usr/include/libxml2'); 37 | s/:s '-DNDEBUG'// for %vars, %vars; 38 | } 39 | 40 | mkdir($destfolder); 41 | LibraryMake::process-makefile($folder, %vars); 42 | shell(%vars); 43 | True; 44 | } 45 | 46 | method build($workdir, Str :$I) { 47 | my $destdir = 'resources/libraries'; 48 | mkdir $destdir; 49 | make($workdir, "$destdir", :libname, :$I); 50 | True; 51 | } 52 | } 53 | 54 | # Build.pm can also be run standalone 55 | sub MAIN(Str $working-directory = '.', Str :$I ) { 56 | Build.new.build($working-directory, :$I); 57 | } 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | docs/index.md -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2015 2 | 3 | platform: x64 4 | 5 | environment: 6 | matrix: 7 | - test_moar: '2018.08' 8 | - test_moar: '2019.07.1' #latest 9 | 10 | install: 11 | - '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64' 12 | - choco install strawberryperl --allow-empty-checksums 13 | - SET PATH=C:\strawberry\c\bin;C:\strawberry\perl\site\bin;C:\strawberry\perl\bin;%PATH% 14 | - git clone https://github.com/tadzik/rakudobrew %USERPROFILE%\rakudobrew 15 | - SET PATH=%USERPROFILE%\rakudobrew\bin;%PATH% 16 | - rakudobrew build moar %TEST_MOAR% 17 | - SET P6INST=%USERPROFILE%\rakudobrew\versions\moar-%TEST_MOAR%\install 18 | - SET P6SHARE=%P6INST%\share\perl6 19 | - SET PATH=%P6INST%\bin;%P6SHARE%\site\bin;%P6SHARE%\bin;%PATH% 20 | - rakudobrew build zef 21 | - cd %APPVEYOR_BUILD_FOLDER% 22 | - set AUTHOR_TESTING=1 23 | - zef --verbose --depsonly install . 24 | 25 | build: off 26 | 27 | test_script: 28 | - zef build . 29 | - prove -ve "perl6 -I." 30 | - zef install . 31 | 32 | shallow_clone: true 33 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | ; dist.ini 2 | name = LibXML 3 | 4 | [ReadmeFromPod] 5 | ; if you want to disable generating README.md from main module's pod, then: 6 | enabled = false 7 | 8 | [UploadToZef] 9 | -------------------------------------------------------------------------------- /docs/CDATA.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [CDATA](https://libxml-raku.github.io/LibXML-raku/CDATA) 4 | 5 | class LibXML::CDATA 6 | ------------------- 7 | 8 | LibXML CDATA Section nodes 9 | 10 | Synopsis 11 | -------- 12 | 13 | use LibXML::CDATA; 14 | # Only methods specific to CDATA nodes are listed here, 15 | # see the LibXML::Node documentation for other methods 16 | 17 | my LibXML::CDATA $cdata .= new( :$content ); 18 | 19 | $cdata.data ~~ s/xxx/yyy/; # Stringy Interface - see LibXML::Text 20 | 21 | Description 22 | ----------- 23 | 24 | This class provides all functions of [LibXML::Text](https://libxml-raku.github.io/LibXML-raku/Text), but for CDATA nodes. 25 | 26 | Methods 27 | ------- 28 | 29 | The class inherits from [LibXML::Node](https://libxml-raku.github.io/LibXML-raku/Node). The documentation for Inherited methods is not listed here. 30 | 31 | Many functions listed here are extensively documented in the DOM Level 3 specification ([http://www.w3.org/TR/DOM-Level-3-Core/](http://www.w3.org/TR/DOM-Level-3-Core/)). Please refer to the specification for extensive documentation. 32 | 33 | ### method new 34 | 35 | method new( Str :$content ) returns LibXML::CDATA 36 | 37 | The constructor is the only provided function for this package. It is required, because *libxml2* treats the different text node types slightly differently. 38 | 39 | Copyright 40 | --------- 41 | 42 | 2001-2007, AxKit.com Ltd. 43 | 44 | 2002-2006, Christian Glahn. 45 | 46 | 2006-2009, Petr Pajas. 47 | 48 | License 49 | ------- 50 | 51 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 52 | 53 | -------------------------------------------------------------------------------- /docs/Comment.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Comment](https://libxml-raku.github.io/LibXML-raku/Comment) 4 | 5 | class LibXML::Comment 6 | --------------------- 7 | 8 | LibXML Comment nodes 9 | 10 | Synopsis 11 | -------- 12 | 13 | use LibXML::Comment; 14 | # Only methods specific to Comment nodes are listed here, 15 | # see the LibXML::Node documentation for other methods 16 | my LibXML::Comment $comment .= new( :$content ); 17 | 18 | $comment.data ~~ s/xxx/yyy/; # Stringy Interface - see LibXML::Text 19 | 20 | Description 21 | ----------- 22 | 23 | This class provides all functions of [LibXML::Text](https://libxml-raku.github.io/LibXML-raku/Text), but for comment nodes. This can be done, since only the output of the node types is different, but not the data structure. :-) 24 | 25 | Methods 26 | ------- 27 | 28 | The class inherits from [LibXML::Node](https://libxml-raku.github.io/LibXML-raku/Node). The documentation for Inherited methods is not listed here. 29 | 30 | Many functions listed here are extensively documented in the DOM Level 3 specification ([http://www.w3.org/TR/DOM-Level-3-Core/](http://www.w3.org/TR/DOM-Level-3-Core/)). Please refer to the specification for extensive documentation. 31 | 32 | ### method new 33 | 34 | method new( Str :$content ) returns LibXML::Comment 35 | 36 | The constructor is the only provided function for this package. It is required, because *libxml2* treats text nodes and comment nodes slightly differently. 37 | 38 | Copyright 39 | --------- 40 | 41 | 2001-2007, AxKit.com Ltd. 42 | 43 | 2002-2006, Christian Glahn. 44 | 45 | 2006-2009, Petr Pajas. 46 | 47 | LICENSE 48 | ------- 49 | 50 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 51 | 52 | -------------------------------------------------------------------------------- /docs/Dict.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Dict](https://libxml-raku.github.io/LibXML-raku/Dict) 4 | 5 | Synopsis 6 | -------- 7 | 8 | my LibXML::Dict $dict .= new; 9 | $dict.see('a'); 10 | $dict.see: ; 11 | say $dict.seen('a'); # True 12 | say $dict.seen('b'); # False 13 | say $dict:exists; # True 14 | say $dict:exists; # False 15 | say $dict.elems; # a x y z 16 | 17 | Description 18 | ----------- 19 | 20 | [LibXML::Dict](https://libxml-raku.github.io/LibXML-raku/Dict) binds to the xmlDict data structure, which is used to uniquely store strings. 21 | 22 | Please see also [LibXML::HashMap](https://libxml-raku.github.io/LibXML-raku/HashMap), for a more general-purpose associative interface. 23 | 24 | -------------------------------------------------------------------------------- /docs/Dtd/AttrDecl.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Dtd](https://libxml-raku.github.io/LibXML-raku/Dtd) 4 | :: [AttrDecl](https://libxml-raku.github.io/LibXML-raku/Dtd/AttrDecl) 5 | 6 | class LibXML::Dtd::AttrDecl 7 | --------------------------- 8 | 9 | LibXML DtD Element attribute declaration introspection (experimental) 10 | 11 | ### Example 12 | 13 | use LibXML::Document; 14 | use LibXML::Dtd; 15 | use LibXML::Dtd::AttrDecl; 16 | use LibXML::Dtd::ElementDecl; 17 | my LibXML::Document $doc .= parse: :file; 18 | my LibXML::Dtd:D $dtd = $doc.getInternalSubset; 19 | my LibXML::Dtd::AttrDecl $doc-foo:attr-decl = $dtd.attribute-declarations; 20 | # Element that contains the attribute declaration 21 | my LibXML::Dtd::ElementDecl $doc:elem-decl = $doc-foo:attr-decl.getElementDecl; 22 | say xmlAttributeType($foo.attrType); 23 | say xmlAttributeDefault($foo.defaultMode); 24 | say $foo.elemName; 25 | say $foo.defaultValue; 26 | 27 | Methods 28 | ------- 29 | 30 | ### AttrType 31 | 32 | Returns the attribute, type. One of: `XML_ATTRIBUTE_CDATA`, `XML_ATTRIBUTE_ID`, `XML_ATTRIBUTE_IDREF`, `XML_ATTRIBUTE_IDREFS`, `XML_ATTRIBUTE_ENTITY`, `XML_ATTRIBUTE_ENTITIES`, `XML_ATTRIBUTE_NMTOKEN`, `XML_ATTRIBUTE_NMTOKENS`, `XML_ATTRIBUTE_ENUMERATION`, or `XML_ATTRIBUTE_NOTATION`. 33 | 34 | ### defaultMode 35 | 36 | Returns the default mode, of of: `XML_ATTRIBUTE_NONE`, `XML_ATTRIBUTE_REQUIRED`, `XML_ATTRIBUTE_IMPLIED`, or `XML_ATTRIBUTE_FIXED`. 37 | 38 | ### defaultValue returns Str 39 | 40 | Returns the default value, if any. 41 | 42 | ### enum 43 | 44 | method values returns Array 45 | say $attr-decl.values; # [a b c] 46 | 47 | Returns an array of possible values, or Array:U , if there is no enumerations. 48 | 49 | This method is applicable to enumerated attributes (AttrType `XML_ATTRIBUTE_ENUMERATION`). 50 | 51 | ### elemName 52 | 53 | Returns the name of the element holding the attribute. 54 | 55 | ### getElementDecl 56 | 57 | ```raku 58 | method getElementDecl() returns LibXML::Dtd::ElementDecl 59 | ``` 60 | 61 | Returns the element declaration associated with this attribute. 62 | 63 | ### prefix 64 | 65 | Returns the namespace prefix, if any. 66 | 67 | -------------------------------------------------------------------------------- /docs/Dtd/ElementDecl.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Dtd](https://libxml-raku.github.io/LibXML-raku/Dtd) 4 | :: [ElementDecl](https://libxml-raku.github.io/LibXML-raku/Dtd/ElementDecl) 5 | 6 | class LibXML::Dtd::ElementDecl 7 | ------------------------------ 8 | 9 | LibXML DtD Element declaration introspection (experimental) 10 | 11 | Example 12 | ------- 13 | 14 | ```raku 15 | use LibXML::Document; 16 | use LibXML::Dtd; 17 | use LibXML::HashMap; 18 | use LibXML::Dtd::ElementDecl; 19 | 20 | my $string = q:to; 21 | 22 | 23 | 24 | 25 | 26 | 27 | END 28 | 29 | my LibXML::Dtd $dtd .= parse: :$string; 30 | my LibXML::HashMap[LibXML::Dtd::ElementDecl] $elements = $dtd.element-decls; 31 | 32 | my LibXML::Dtd::ElementDecl $note-decl = $elements; 33 | note $note-decl.Str; # 34 | note $note-decl.content.potential-children; # [to from heading body] 35 | note $node-decl.attributes.Str; # 36 | ``` 37 | 38 | Methods 39 | ------- 40 | 41 | ### method content 42 | 43 | ```raku 44 | method content() returns LibXML::Dtd::ElementContent 45 | ``` 46 | 47 | return the parsed content expression for this element declaration 48 | 49 | ### method properties 50 | 51 | ```raku 52 | method properties() returns Array[LibXML::Dtd::AttrDecl] 53 | ``` 54 | 55 | return a read-only list of attribute declarations 56 | 57 | for example: 58 | 59 | ```raku 60 | use LibXML::Dtd; 61 | my LibXML::Dtd $dtd .= parse: :string(q:to); 62 | 63 | 67 | END 68 | 69 | my $A:decl = $dtd.element-declarations; 70 | 71 | for $A:decl.properties { 72 | print .Str; 73 | } 74 | ``` 75 | 76 | Produces: 77 | 78 | 79 | 80 | 81 | ### method attributes 82 | 83 | ```raku 84 | method attributes() returns Mu 85 | ``` 86 | 87 | return a read-only hash of attribute declarations 88 | 89 | ### method prefix 90 | 91 | Returns a namespace prefix, if any. 92 | 93 | -------------------------------------------------------------------------------- /docs/Dtd/Entity.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Dtd](https://libxml-raku.github.io/LibXML-raku/Dtd) 4 | :: [Entity](https://libxml-raku.github.io/LibXML-raku/Dtd/Entity) 5 | 6 | class LibXML::Dtd::Entity 7 | ------------------------- 8 | 9 | DtD entity definitions 10 | 11 | Example 12 | ------- 13 | 14 | ```raku 15 | use LibXML::Document; 16 | use LibXML::Dtd::Entity; 17 | use LibXML::Enums; 18 | 19 | my $string = q:to; 20 | 21 | END 22 | 23 | my LibXML::Dtd $dtd .= parse: :$string; 24 | my LibXML::Dtd::Entity $ent = $dtd.entities; 25 | 26 | note $ent.name; # foo 27 | note $ent.value; # Fooo 28 | say xmlEntityType($ent.entityType); # XML_INTERNAL_GENERAL_ENTITY 29 | note $ent.Str; # 30 | ``` 31 | 32 | ### method publicId 33 | 34 | ```raku 35 | method publicId() returns Str 36 | ``` 37 | 38 | return the Public (External) ID 39 | 40 | ### method systemId 41 | 42 | ```raku 43 | method systemId() returns Str 44 | ``` 45 | 46 | Return the System ID 47 | 48 | ### method name 49 | 50 | ```raku 51 | method name() returns Str 52 | ``` 53 | 54 | Return the entity name 55 | 56 | ### method notationName 57 | 58 | ```raku 59 | method notationName() returns Mu 60 | ``` 61 | 62 | return the name of any notation associated with this entity 63 | 64 | ### method notation 65 | 66 | ```raku 67 | method notation() returns LibXML::Dtd::Notation 68 | ``` 69 | 70 | return any notation associated with this entity 71 | 72 | ### method entityType 73 | 74 | ```raku 75 | method entityType() returns Mu 76 | ``` 77 | 78 | return the entity type 79 | 80 | One of: `XML_EXTERNAL_GENERAL_PARSED_ENTITY`, `XML_EXTERNAL_GENERAL_UNPARSED_ENTITY`, `XML_EXTERNAL_PARAMETER_ENTITY`, `XML_INTERNAL_GENERAL_ENTITY`, `XML_INTERNAL_PARAMETER_ENTITY`, or `XML_INTERNAL_PREDEFINED_ENTITY` 81 | 82 | -------------------------------------------------------------------------------- /docs/Dtd/Notation.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Dtd](https://libxml-raku.github.io/LibXML-raku/Dtd) 4 | :: [Notation](https://libxml-raku.github.io/LibXML-raku/Dtd/Notation) 5 | 6 | class LibXML::Dtd::Notation 7 | --------------------------- 8 | 9 | LibXML DtD notations 10 | 11 | ### Example 12 | 13 | ```raku 14 | use LibXML::Dtd; 15 | use LibXML::Dtd::Notation; 16 | 17 | my $string = q:to; 18 | 19 | 20 | 23 | END 24 | 25 | my LibXML::Dtd $dtd .= parse: :$string; 26 | my LibXML::Dtd::Notation $notation = $dtd.notations; 27 | $notation = $dtd.entities.notation; 28 | 29 | say $notation.name; # png 30 | say $notation.systemId; # image/png 31 | say $notation.Str; # 32 | ``` 33 | 34 | ### Description 35 | 36 | Notation declarations are an older mechanism that is sometimes used in a DTD to qualify the data contained within an external entity (non-xml) file. 37 | 38 | ### method publicId 39 | 40 | ```raku 41 | method publicId() returns Str 42 | ``` 43 | 44 | Return the Public (External) ID 45 | 46 | ### method systemId 47 | 48 | ```raku 49 | method systemId() returns Str 50 | ``` 51 | 52 | Return the System ID 53 | 54 | ### method nodeName 55 | 56 | ```raku 57 | method nodeName() returns Str 58 | ``` 59 | 60 | Return the entity name 61 | 62 | -------------------------------------------------------------------------------- /docs/Enums.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Enums](https://libxml-raku.github.io/LibXML-raku/Enums) 4 | 5 | module LibXML::Enums 6 | -------------------- 7 | 8 | Native enumerations 9 | 10 | Description 11 | ----------- 12 | 13 | The Lib::XML::Enums module exports a large number of libxml2 native enumerations. 14 | 15 | All are prefixed `XML_*`. 16 | 17 | These are mostly low-level and encapsulated by LibXML. For example for nodes of type [LibXML::Element](https://libxml-raku.github.io/LibXML-raku/Element) always have a `type` of `XML_ELEMENT_NODE`. 18 | 19 | The `code` attribute of X::LibXML exceptions (see [LibXML::ErrorHandling](https://libxml-raku.github.io/LibXML-raku/ErrorHandling)) may be useful, if you wish to detect various libxml errors, for example: 20 | 21 | use LibXML; 22 | use LibXML::Enums; 23 | 24 | try LibXML.parse: :string("42"); 25 | with $! -> X::LibXML $err { 26 | if $err.code == XML_ERR_TAG_NAME_MISMATCH { 27 | warn "your tags don't match"; 28 | } 29 | else { 30 | warn $err; 31 | } 32 | } 33 | 34 | The libxml [error documentation](error documentation) lists possible error codes. Enumerations should be defined for all of these. 35 | 36 | License 37 | ------- 38 | 39 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 40 | 41 | -------------------------------------------------------------------------------- /docs/Node/List.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Node](https://libxml-raku.github.io/LibXML-raku/Node) 4 | :: [List](https://libxml-raku.github.io/LibXML-raku/Node/List) 5 | 6 | class LibXML::Node::List 7 | ------------------------ 8 | 9 | LibXML Sibling Node Lists 10 | 11 | Synopsis 12 | -------- 13 | 14 | use LibXML::Node::List; 15 | my LibXML::Node::List $node-list, $att-list; 16 | 17 | $att-list = $elem.attributes; 18 | $node-list = $elem.childNodes; 19 | $node-list.push: $elem; 20 | 21 | for $node-list -> LibXML::Node $item { ... } 22 | for ^$node-set.elems { my $item = $node-set[$_]; ... } 23 | 24 | my LibXML::Node::Set %nodes-by-xpath-name = $node-list.Hash; 25 | # ... 26 | 27 | Description 28 | ----------- 29 | 30 | This class is used for traversing child nodes or attribute lists. 31 | 32 | Unlike node-sets, the list is tied to the DOM and can be used to update nodes. 33 | 34 | # replace 4th child 35 | $node-list[3] = LibXML::TextNode.new :content("Replacement Text"); 36 | # remove last child 37 | my $deleted-node = $node-set.pop; 38 | # append a new child element 39 | $node-set.push: LibXML::Element.new(:name); 40 | 41 | Currently, the only tied methods are `push`, `pop` and `ASSIGN-POS`. 42 | 43 | Copyright 44 | --------- 45 | 46 | 2001-2007, AxKit.com Ltd. 47 | 48 | 2002-2006, Christian Glahn. 49 | 50 | 2006-2009, Petr Pajas. 51 | 52 | License 53 | ------- 54 | 55 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 56 | 57 | -------------------------------------------------------------------------------- /docs/RegExp.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [RegExp](https://libxml-raku.github.io/LibXML-raku/RegExp) 4 | 5 | class LibXML::RegExp 6 | -------------------- 7 | 8 | interface to libxml2 regular expressions 9 | 10 | Synopsis 11 | -------- 12 | 13 | use LibXML::RegExp; 14 | my LibXML::RegExp $compiled-re .= compile('[0-9]{5}(-[0-9]{4})?'); 15 | my LibXML::RegExp $compiled-re .= new(rexexp => '[0-9]{5}(-[0-9]{4})?'); 16 | if $compiled-re.isDeterministic() { ... } 17 | if $compiled-re.matches($string) { ... } 18 | if $string ~~ $compiled-re { ... } 19 | 20 | my LibXML::RegExp $compiled-re .= new( :$regexp ); 21 | my Bool $matched = $compiled-re.matches($string); 22 | my Bool $det = $compiled-re.isDeterministic(); 23 | 24 | Description 25 | ----------- 26 | 27 | This is a Raku interface to libxml2's implementation of regular expressions, which are used e.g. for validation of XML Schema simple types (pattern facet). 28 | 29 | Methods 30 | ------- 31 | 32 | method new 33 | ---------- 34 | 35 | method new(Str :$regexp) returns LibXML 36 | my LibXML::RegExp $compiled-re .= new( :$regexp ); 37 | 38 | The new constructor takes a string containing a regular expression and return an object that contains a compiled regexp. 39 | 40 | ### method compile 41 | 42 | ```raku 43 | method compile( 44 | Str:D $regexp 45 | ) returns LibXML::RegExp 46 | ``` 47 | 48 | Compile constructor 49 | 50 | `LibXML::RegExp.compile($regexp)` is equivalent to `LibXML::RegExp.new(:$regexp)` 51 | 52 | ### multi method ACCEPTS 53 | 54 | ```raku 55 | multi method ACCEPTS( 56 | Str:D $content 57 | ) returns Bool 58 | ``` 59 | 60 | (alias matches) Returns True if $content matches the regular expression 61 | 62 | ### method isDeterministic 63 | 64 | ```raku 65 | method isDeterministic() returns Bool 66 | ``` 67 | 68 | Returns True if the regular expression is deterministic. 69 | 70 | (See the definition of determinism in the XML spec [http://www.w3.org/TR/REC-xml/#determinism ](http://www.w3.org/TR/REC-xml/#determinism )) 71 | 72 | Copyright 73 | --------- 74 | 75 | 2001-2007, AxKit.com Ltd. 76 | 77 | 2002-2006, Christian Glahn. 78 | 79 | 2006-2009, Petr Pajas. 80 | 81 | License 82 | ------- 83 | 84 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 85 | 86 | -------------------------------------------------------------------------------- /docs/SAX/Builder.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [SAX](https://libxml-raku.github.io/LibXML-raku/SAX) 4 | :: [Builder](https://libxml-raku.github.io/LibXML-raku/SAX/Builder) 5 | 6 | class LibXML::SAX::Builder 7 | -------------------------- 8 | 9 | Builds SAX callback sets 10 | 11 | class LibXML::SAX::Builder::NsAtt 12 | --------------------------------- 13 | 14 | for marshalling of startElementNs attributes 15 | 16 | Description 17 | ----------- 18 | 19 | This class provides mappings from native SAX2 callbacks to Raku. 20 | 21 | It may be used in conjunction with [LibXML::SAX::Handler::SAX2](https://libxml-raku.github.io/LibXML-raku/SAX/Handler/SAX2) base-class. 22 | 23 | Example 24 | ------- 25 | 26 | The following example builds a modified DOM tree with all tags and attributes converted to uppercase. 27 | 28 | use LibXML::Document; 29 | use LibXML::SAX::Builder; 30 | use LibXML::SAX::Handler::SAX2; 31 | 32 | class SAXShouter is LibXML::SAX::Handler::SAX2 { 33 | use LibXML::SAX::Builder :sax-cb; 34 | method startElement($name, |c) is sax-cb { 35 | nextwith($name.uc, |c); 36 | } 37 | method endElement($name, |c) is sax-cb { 38 | nextwith($name.uc, |c); 39 | } 40 | method characters($chars, |c) is sax-cb { 41 | nextwith($chars.uc, |c); 42 | } 43 | } 44 | 45 | my SAXShouter $sax-handler .= new(); 46 | my $string = '

Hello World

' 47 | my LibXML::Document $doc .= parse: :$string, :$sax-handler; 48 | say $doc.Str; #

HELLO WORLD

' 49 | 50 | See [LibXML::SAX::Handler::SAX2](https://libxml-raku.github.io/LibXML-raku/SAX/Handler/SAX2) for a description of callbacks 51 | 52 | Copyright 53 | --------- 54 | 55 | 2001-2007, AxKit.com Ltd. 56 | 57 | 2002-2006, Christian Glahn. 58 | 59 | 2006-2009, Petr Pajas. 60 | 61 | License 62 | ------- 63 | 64 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 65 | 66 | -------------------------------------------------------------------------------- /docs/SAX/Handler/XML.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [SAX](https://libxml-raku.github.io/LibXML-raku/SAX) 4 | :: [Handler](https://libxml-raku.github.io/LibXML-raku/SAX/Handler) 5 | :: [XML](https://libxml-raku.github.io/LibXML-raku/SAX/Handler/XML) 6 | 7 | class LibXML::SAX::Handler::XML 8 | ------------------------------- 9 | 10 | Build pure Raku XML documents using LibXML's SAX parser 11 | 12 | Synopsis 13 | -------- 14 | 15 | use LibXML; 16 | use LibXML::SAX::Handler::XML; 17 | use XML::Document; 18 | 19 | my LibXML::SAX::Handler::XML $sax-handler .= new; 20 | my XML::Document $doc = LibXML.parse: :file, :$sax-handler; 21 | 22 | Description 23 | ----------- 24 | 25 | [LibXML::SAX::Handler::XML](https://libxml-raku.github.io/LibXML-raku/SAX/Handler/XML) is a SAX handler that produce a pure Raku [XML::Document](https://github.com/raku-community-modules/XML) object using the LIBXML SAX interface to parse the document. 26 | 27 | This class is an example of implementing a custom parser using the LibXML SAX interface, [LibXML::SAX::Builder](https://libxml-raku.github.io/LibXML-raku/SAX/Builder) and [LibXML::SAX::Handler::SAX2](https://libxml-raku.github.io/LibXML-raku/SAX/Handler/SAX2). 28 | 29 | -------------------------------------------------------------------------------- /docs/Threads.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [Threads](https://libxml-raku.github.io/LibXML-raku/Threads) 4 | 5 | Notes on Raku LibXML Threading and Concurrency 6 | ============================================== 7 | 8 | Concurrency and Parsing 9 | ----------------------- 10 | 11 | Parsing, including, validation and the Reader pull-parser can be run concurrently. 12 | 13 | ```raku 14 | my @docs = @files.hyper.map: -> $file { LibXML::Parse: :$file } 15 | ``` 16 | 17 | However, the Raku LibXML bindings will protect these with a commonly library lock, defeating concurrency, if the libxml library has not been compiled with threading enabled. Threading can be checked using the [LibXML::Config](https://libxml-raku.github.io/LibXML-raku/Config) `threads` method. 18 | 19 | ```raku 20 | unless LibXML::Config.threads { ... } 21 | ``` 22 | 23 | ### Concurrency and Input Callbacks 24 | 25 | Input callbacks may be set globally, without affecting concurrency. 26 | 27 | ```raku 28 | my LibXML::InputCallback $input-callbacks .= new: @callbacks; 29 | LibXML::Config.input-callbacks = $input-callbacks; 30 | ``` 31 | 32 | They may also be set at the parser level. However, this is not thread safe. The LibXML library requires that you also enable the `parser-locking` flag, which limits concurrent parsing. 33 | 34 | ```raku 35 | LibXML::Config.parser-locking = True; 36 | my LibXML::InputCallback $input-callbacks .= new: :callbacks{ 37 | :&match, :&read, :&open, :&close 38 | } 39 | LibXML::Config.parser-locking = True; 40 | my LibXML:D $parser .= new: :$input-callbacks; 41 | ``` 42 | 43 | DOM Concurrency 44 | --------------- 45 | 46 | ### Parallel Construction 47 | 48 | Document fragments and element sub-trees, may be constructed in parallel provided that they remain independent of each other. They then need to be assembled sequentially to create the final document: 49 | 50 | ```raku 51 | my LibXML::Document $doc .= parse: :string(""); 52 | my @frags = @files.hyper.map: -> $file { LibXML::DocumentFragment.parse: :balanced, :$file} 53 | $doc.addChild($_) for @frags; 54 | ``` 55 | 56 | ### DOM Updates and Concurrency 57 | 58 | It is not thread-safe to read and modify DOM nodes concurrently. 59 | 60 | However, each node has a `protect` method that can be used to limit concurrency. 61 | 62 | ```raku 63 | $elem.protect: { $elem.appendChild: LibXML::Element.new('foo') } 64 | ``` 65 | 66 | Be careful with nesting `protect` calls, to avoid potential deadlocks. 67 | 68 | -------------------------------------------------------------------------------- /docs/XInclude/Context.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [XInclude](https://libxml-raku.github.io/LibXML-raku/XInclude) 4 | :: [Context](https://libxml-raku.github.io/LibXML-raku/XInclude/Context) 5 | 6 | class LibXML::XInclude::Context 7 | ------------------------------- 8 | 9 | XInclude Processing Context 10 | 11 | Synopsis 12 | -------- 13 | 14 | use LibXML::XInclude::Context; 15 | my LibXML::XInclude::Context $xic .= new(); 16 | $xic.process-xincludes($doc); 17 | 18 | Description 19 | ----------- 20 | 21 | XInclude processing context. 22 | 23 | Methods 24 | ------- 25 | 26 | Copyright 27 | --------- 28 | 29 | 2001-2007, AxKit.com Ltd. 30 | 31 | 2002-2006, Christian Glahn. 32 | 33 | 2006-2009, Petr Pajas. 34 | 35 | License 36 | ------- 37 | 38 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 39 | 40 | -------------------------------------------------------------------------------- /docs/XPath/Expression.md: -------------------------------------------------------------------------------- 1 | [[Raku LibXML Project]](https://libxml-raku.github.io) 2 | / [[LibXML Module]](https://libxml-raku.github.io/LibXML-raku) 3 | / [XPath](https://libxml-raku.github.io/LibXML-raku/XPath) 4 | :: [Expression](https://libxml-raku.github.io/LibXML-raku/XPath/Expression) 5 | 6 | class LibXML::XPath::Expression 7 | ------------------------------- 8 | 9 | Interface to LibXML pre-compiled XPath Expressions 10 | 11 | Synopsis 12 | -------- 13 | 14 | use LibXML::XPath::Expression; 15 | my LibXML::XPath::Expression $compiled-xpath .= compile('//foo[@bar="baz"][position()<4]'); 16 | 17 | # interface from LibXML::Node 18 | 19 | my $result = $node.find($compiled-xpath); 20 | my @nodes = $node.findnodes($compiled-xpath); 21 | my $value = $node.findvalue($compiled-xpath); 22 | 23 | # interface from LibXML::XPath::Context 24 | 25 | my $result = $xpc.find($compiled-xpath, $node); 26 | my @nodes = $xpc.findnodes($compiled-xpath, $node); 27 | my $value = $xpc.findvalue($compiled-xpath, $node); 28 | 29 | my LibXML::XPath::Expression $compiled .= new: :expr($xpath-string), :$node; 30 | 31 | Description 32 | ----------- 33 | 34 | This is a Raku interface to libxml2's pre-compiled XPath expressions. Pre-compiling an XPath expression can give in some performance benefit if the same XPath query is evaluated many times. `LibXML::XPath::Expression` objects can be passed to all `find...` functions in [LibXML](https://libxml-raku.github.io/LibXML-raku) that expect an XPath expression. 35 | 36 | Methods 37 | ------- 38 | 39 | ### method new 40 | 41 | method new( 42 | Str :expr($xpath)!, LibXML::Node :node($ref-node) 43 | ) returns LibXML::XPath::Expression 44 | 45 | The constructor takes an XPath 1.0 expression as a string and returns an object representing the pre-compiled expressions (the actual data structure is internal to libxml2). 46 | 47 | ### method compile 48 | 49 | method compile( 50 | Str $xpath, 51 | LibXML::Node :node($ref-node) 52 | ) returns LibXML::XPath::Expression; 53 | 54 | Alternative constructor which takes a positional XPath expression as a string. 55 | 56 | Copyright 57 | --------- 58 | 59 | 2001-2007, AxKit.com Ltd. 60 | 61 | 2002-2006, Christian Glahn. 62 | 63 | 2006-2009, Petr Pajas. 64 | 65 | License 66 | ------- 67 | 68 | This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 [http://www.perlfoundation.org/artistic_license_2_0](http://www.perlfoundation.org/artistic_license_2_0). 69 | 70 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /etc/resolve-links.raku: -------------------------------------------------------------------------------- 1 | constant DocRoot = "https://libxml-raku.github.io"; 2 | 3 | multi sub resolve-class(@ ('LibXML', 'Writer', *@path)) { 4 | %( :repo, :@path ); 5 | } 6 | 7 | multi sub resolve-class(@ ('LibXML', *@path)) { 8 | %( :repo, :@path ); 9 | } 10 | 11 | multi sub resolve-class(@ ('W3C', 'DOM', *@)) { 12 | %( :repo, ) 13 | } 14 | 15 | multi sub resolve-class(@ ('LibXSLT', *@p)) { 16 | my @path; 17 | with @p.head { 18 | when 'Stylesheet'|'Security' { 19 | @path.push: $_; 20 | } 21 | } 22 | %( :repo, :@path) 23 | } 24 | 25 | multi sub resolve-class(@ ('XML', *@p)) { 26 | %( :repo, :url) 27 | } 28 | 29 | sub link-to-url(Str() $class-name) { 30 | my %info = resolve-class($class-name.split('::')); 31 | %info // do { 32 | my @path = DocRoot; 33 | @path.push: %info; 34 | @path.append(.list) with %info; 35 | @path.join: '/'; 36 | } 37 | } 38 | 39 | sub breadcrumb(Str $url is copy, @path, UInt $n = +@path, :$top) { 40 | my $name = $top ?? @path[0 ..^ $n].join('::') !! @path[$n-1]; 41 | $url ~= '/' ~ @path[0 ..^ $n].join('/'); 42 | my $sep = $top ?? '/' !! '::'; 43 | say " $sep [$name]($url)"; 44 | } 45 | 46 | INIT { 47 | with %*ENV { 48 | # build a simple breadcrumb trail 49 | my %info = resolve-class(.split('/')); 50 | my $repo = %info; 51 | say "[[Raku LibXML Project]]({%info // DocRoot})"; 52 | 53 | my @mod = $repo.split('-'); 54 | @mod.pop if @mod.tail ~~ 'raku'; 55 | my $mod = @mod.join: '-'; 56 | my $url = %info // DocRoot ~ '/' ~ $repo; 57 | say " / [[$mod Module]]({$url})"; 58 | 59 | with %info { 60 | my @path = .list; 61 | if @path { 62 | my $n = @path[0..^+@mod] == @mod ?? 1 !! 2; 63 | breadcrumb($url, @path, $n, :top); 64 | breadcrumb($url, @path, $_) 65 | for $n ^.. @path; 66 | } 67 | } 68 | say ''; 69 | } 70 | } 71 | 72 | s:g:s/ '](' ([W3C|[Lib]?X[ML|SLT]]['::'*%%]) ')'/{'](' ~ link-to-url($0) ~ ')'}/; 73 | -------------------------------------------------------------------------------- /lib/LibXML/CDATA.rakumod: -------------------------------------------------------------------------------- 1 | #| LibXML CDATA Section nodes 2 | unit class LibXML::CDATA; 3 | 4 | use LibXML::Node; 5 | use LibXML::Raw; 6 | use LibXML::_CharacterData; 7 | use LibXML::_Rawish; 8 | use W3C::DOM; 9 | 10 | also is LibXML::Node; 11 | also does LibXML::_CharacterData; 12 | also does LibXML::_Rawish[xmlCDataNode]; 13 | also does W3C::DOM::CDATASection; 14 | 15 | use NativeCall; 16 | use Method::Also; 17 | 18 | method data is rw is also handles { $.raw.content }; 19 | 20 | =begin pod 21 | =head2 Synopsis 22 | 23 | use LibXML::CDATA; 24 | # Only methods specific to CDATA nodes are listed here, 25 | # see the LibXML::Node documentation for other methods 26 | 27 | my LibXML::CDATA $cdata .= new( :$content ); 28 | 29 | $cdata.data ~~ s/xxx/yyy/; # Stringy Interface - see LibXML::Text 30 | 31 | =head2 Description 32 | 33 | This class provides all functions of L, but for CDATA nodes. 34 | 35 | =head2 Methods 36 | 37 | The class inherits from L. The documentation for Inherited methods is not listed here. 38 | 39 | Many functions listed here are extensively documented in the DOM Level 3 specification (L). Please refer to the specification for extensive documentation. 40 | 41 | =head3 method new 42 | 43 | method new( Str :$content ) returns LibXML::CDATA 44 | 45 | The constructor is the only provided function for this package. It is required, 46 | because I treats the different text node types slightly differently. 47 | 48 | =head2 Copyright 49 | 50 | 2001-2007, AxKit.com Ltd. 51 | 52 | 2002-2006, Christian Glahn. 53 | 54 | 2006-2009, Petr Pajas. 55 | 56 | =head2 License 57 | 58 | This program is free software; you can redistribute it and/or modify it under 59 | the terms of the Artistic License 2.0 L. 60 | 61 | =end pod 62 | -------------------------------------------------------------------------------- /lib/LibXML/Comment.rakumod: -------------------------------------------------------------------------------- 1 | #| LibXML Comment nodes 2 | unit class LibXML::Comment; 3 | 4 | use LibXML::Node; 5 | use LibXML::Raw; 6 | use LibXML::_CharacterData; 7 | use LibXML::_Rawish; 8 | use W3C::DOM; 9 | 10 | also is LibXML::Node; 11 | also does LibXML::_CharacterData; 12 | also does LibXML::_Rawish[xmlCommentNode]; 13 | also does W3C::DOM::Comment; 14 | 15 | use NativeCall; 16 | use Method::Also; 17 | 18 | method data is also is rw handles { $.raw.content }; 19 | 20 | =begin pod 21 | =head2 Synopsis 22 | 23 | use LibXML::Comment; 24 | # Only methods specific to Comment nodes are listed here, 25 | # see the LibXML::Node documentation for other methods 26 | my LibXML::Comment $comment .= new( :$content ); 27 | 28 | $comment.data ~~ s/xxx/yyy/; # Stringy Interface - see LibXML::Text 29 | 30 | =head2 Description 31 | 32 | This class provides all functions of L, but for comment nodes. This can be done, since only the output of the node 33 | types is different, but not the data structure. :-) 34 | 35 | =head2 Methods 36 | 37 | The class inherits from L. The documentation for Inherited methods is not listed here. 38 | 39 | Many functions listed here are extensively documented in the DOM Level 3 specification (L). Please refer to the specification for extensive documentation. 40 | 41 | =head3 method new 42 | 43 | method new( Str :$content ) returns LibXML::Comment 44 | 45 | The constructor is the only provided function for this package. It is required, 46 | because I treats text nodes and comment nodes slightly differently. 47 | 48 | =head2 Copyright 49 | 50 | 2001-2007, AxKit.com Ltd. 51 | 52 | 2002-2006, Christian Glahn. 53 | 54 | 2006-2009, Petr Pajas. 55 | 56 | =head2 LICENSE 57 | 58 | This program is free software; you can redistribute it and/or modify it under 59 | the terms of the Artistic License 2.0 L. 60 | 61 | =end pod 62 | -------------------------------------------------------------------------------- /lib/LibXML/DOM.pod6: -------------------------------------------------------------------------------- 1 | =begin pod 2 | =head1 Raku LibXML DOM Interface 3 | 4 | The L a platform and language independent interface for accessing and manipulating documents. 5 | 6 | L uses the L module to map classes and methods. 7 | 8 | A quick summary of the Raku DOM implementation follows: 9 | =begin table 10 | W3C::DOM Role | W3C::DOM Parent | LibXML Class | L1 Methods | L2 Methods | NYI 11 | ===========+========+===============+============+=========== 12 | Node | | LibXML::Node | nodeName nodeValue parentNode childNodes firstChild lastChild previousSibling nextSibling ownerDocument insertBefore replaceChild removeChild appendChild hasChildNodes cloneNode | normalize isSupported namespaceURI prefix localName hasAttributes | 13 | CharacterData | Node | | data length substringData appendData insertData deleteData replaceData 14 | Attr | Node | LibXML::Attr | name value | ownerElement | specified 15 | CDATASection | Text | LibXML::CDATA | splitText 16 | Comment | CharacterData | LibXML::Comment 17 | Document | Node | LibXML::Document | doctype implementation documentElement createElement createDocumentFragment createTextNode createComment createCDATASection createProcessingInstruction createAttribute createEntityReference getElementsByTagName | importNode createElementNS createAttributeNS getElementsByTagNameNS getElementById 18 | DocumentFragment | Node | LibXML::DocumentFragment 19 | DocumentType | Node | LibXML::Dtd | name publicId systemId entities notations| | 20 | Element | Node | LibXML::Element | attributes getAttribute setAttribute removeAttribute getAttributeNode setAttributeNode removeAttributeNode getElementsByTagName | getAttributeNS setAttributeNS removeAttributeNS getAttributeNodeNS setAttributeNodeNS getElementsByTagNameNS hasAttribute hasAttributeNS 21 | Entity | Node | LibXML::Dtd::Entity | publicId systemId notationName 22 | EntityReference | Node | LibXML::EntityRef 23 | Implementation | | LibXML | createDocument createDocumentType hasFeature 24 | NamedNodeMap | | LibXML::Attr::Map | getNamedItem setNamedItem removeNamedItem item length | getNamedItemNS setNamedItemNS removeNamedItemNS 25 | Notation | Node | LibXML::Dtd::Notation | nodeName publicId systemId | N/A [1] 26 | ProcessingInstruction | Node | LibXML::PI | target data 27 | Text | CharacterData | LibXML::Text | splitText | | 28 | 29 | =end table 30 | 31 | =item [1] This object is stored in a LibXML hash-table, so most DOM manipulation methods are not applicable 32 | =end pod -------------------------------------------------------------------------------- /lib/LibXML/Dict.rakumod: -------------------------------------------------------------------------------- 1 | use v6; 2 | unit class LibXML::Dict does Associative; 3 | 4 | use LibXML::Raw::Dict; 5 | use Method::Also; 6 | 7 | has xmlDict $!native; 8 | 9 | submethod TWEAK(xmlDict:D :$!native = xmlDict.new) { 10 | $!native.Reference; 11 | } 12 | 13 | submethod DESTROY { 14 | .Unreference with $!native; 15 | } 16 | 17 | method of { Str } 18 | method key-of { Str } 19 | 20 | method elems { $!native.Size } 21 | 22 | method AT-KEY(Str() $key) { $!native.Exists($key, -1); } 23 | method EXISTS-KEY(Str() $key) is also { ? $!native.Exists($key, -1); } 24 | method ASSIGN-KEY(Str() $key, Str() $ where $key) is rw { $!native.Lookup($key, -1); $key } 25 | 26 | multi method see(Str:D() $key) { 27 | $!native.Lookup($key, -1); 28 | } 29 | multi method see(@k) { 30 | $!native.Lookup($_, -1) for @k; 31 | } 32 | 33 | =begin pod 34 | 35 | =head2 Synopsis 36 | 37 | my LibXML::Dict $dict .= new; 38 | $dict.see('a'); 39 | $dict.see: ; 40 | say $dict.seen('a'); # True 41 | say $dict.seen('b'); # False 42 | say $dict
:exists; # True 43 | say $dict:exists; # False 44 | say $dict.elems; # a x y z 45 | 46 | =head2 Description 47 | 48 | L binds to the xmlDict data structure, which is used to uniquely store strings. 49 | 50 | Please see also L, for a more general-purpose associative interface. 51 | 52 | =end pod 53 | -------------------------------------------------------------------------------- /lib/LibXML/Dtd/Entity.rakumod: -------------------------------------------------------------------------------- 1 | #| DtD entity definitions 2 | unit class LibXML::Dtd::Entity; 3 | 4 | use LibXML::Node; 5 | use LibXML::Raw; 6 | use LibXML::_Rawish; 7 | 8 | also is LibXML::Node; 9 | also does LibXML::_Rawish[xmlEntity]; 10 | 11 | use LibXML::Enums; 12 | use NativeCall; 13 | use LibXML::Dtd::Notation; 14 | 15 | method new(Str:D :$name!, Str:D :$content!, Str :$external-id, Str :$internal-id, LibXML::Item :$doc) { 16 | my xmlEntity:D $native .= create: :$name, :$content, :$external-id, :$internal-id; 17 | self.box($native, :$doc); 18 | } 19 | 20 | =begin pod 21 | =head2 Example 22 | 23 | =begin code :lang 24 | use LibXML::Document; 25 | use LibXML::Dtd::Entity; 26 | use LibXML::Enums; 27 | 28 | my $string = q:to; 29 | 30 | END 31 | 32 | my LibXML::Dtd $dtd .= parse: :$string; 33 | my LibXML::Dtd::Entity $ent = $dtd.entities; 34 | 35 | note $ent.name; # foo 36 | note $ent.value; # Fooo 37 | say xmlEntityType($ent.entityType); # XML_INTERNAL_GENERAL_ENTITY 38 | note $ent.Str; # 39 | =end code 40 | =end pod 41 | 42 | #| return the Public (External) ID 43 | method publicId(--> Str) { $.raw.ExternalID } 44 | 45 | #| Return the System ID 46 | method systemId(--> Str) { $.raw.SystemID } 47 | 48 | #| Return the entity name 49 | method name(--> Str) { $.raw.name } 50 | 51 | #| return the name of any notation associated with this entity 52 | method notationName { 53 | self.raw.etype == XML_INTERNAL_PREDEFINED_ENTITY 54 | ?? Str 55 | !! $.raw.content; 56 | } 57 | 58 | #| return any notation associated with this entity 59 | method notation(--> LibXML::Dtd::Notation) { 60 | do with $.notationName { 61 | with $.raw.parent -> $dtd { 62 | LibXML::Dtd::Notation.box: $dtd.delegate.getNotation($_); 63 | } 64 | } // LibXML::Dtd::Notation; 65 | } 66 | 67 | #| return the entity type 68 | method entityType { $.raw.etype } 69 | =para One of: `XML_EXTERNAL_GENERAL_PARSED_ENTITY`, 70 | `XML_EXTERNAL_GENERAL_UNPARSED_ENTITY`, 71 | `XML_EXTERNAL_PARAMETER_ENTITY`, 72 | `XML_INTERNAL_GENERAL_ENTITY`, 73 | `XML_INTERNAL_PARAMETER_ENTITY`, 74 | or `XML_INTERNAL_PREDEFINED_ENTITY` 75 | 76 | method Str { 77 | self.defined && self.raw.etype == XML_INTERNAL_PREDEFINED_ENTITY 78 | ?? $.raw.content 79 | !! nextsame; 80 | } 81 | -------------------------------------------------------------------------------- /lib/LibXML/Dtd/Notation.rakumod: -------------------------------------------------------------------------------- 1 | #| LibXML DtD notations 2 | unit class LibXML::Dtd::Notation; 3 | 4 | use W3C::DOM; 5 | 6 | also does W3C::DOM::Notation; 7 | 8 | use LibXML::Raw; 9 | use NativeCall; 10 | use Method::Also; 11 | 12 | =begin pod 13 | 14 | =head3 Example 15 | 16 | =begin code :lang 17 | use LibXML::Dtd; 18 | use LibXML::Dtd::Notation; 19 | 20 | my $string = q:to; 21 | 22 | 23 | 26 | END 27 | 28 | my LibXML::Dtd $dtd .= parse: :$string; 29 | my LibXML::Dtd::Notation $notation = $dtd.notations; 30 | $notation = $dtd.entities.notation; 31 | 32 | say $notation.name; # png 33 | say $notation.systemId; # image/png 34 | say $notation.Str; # 35 | =end code 36 | 37 | =head3 Description 38 | 39 | Notation declarations are an older mechanism that is sometimes used in a DTD to qualify the data contained within an external entity (non-xml) file. 40 | 41 | =end pod 42 | 43 | has xmlNotation:D $.raw handles is required; 44 | 45 | method new(Str:D :$name!, Str :$publicId, Str :$systemId, *%c) { 46 | my xmlNotation:D $raw .= new(:$name, :$publicId, :$systemId); 47 | self.bless: :$raw, |%c; 48 | } 49 | method box(xmlNotation:D $raw is copy, |c --> LibXML::Dtd::Notation) { 50 | $raw .= Copy; 51 | self.bless: :$raw, |c 52 | } 53 | method unique-key returns Str { $.raw.UniqueKey.Str } 54 | method isSame($_) is also { 55 | .isa($?CLASS) && self.unique-key eq .unique-key 56 | } 57 | 58 | =head3 method publicId 59 | 60 | =for code :lang 61 | method publicId() returns Str 62 | 63 | =para Return the Public (External) ID 64 | 65 | =head3 method systemId 66 | 67 | =for code :lang 68 | method systemId() returns Str 69 | 70 | =para Return the System ID 71 | 72 | # DOM 73 | 74 | #| Return the entity name 75 | method nodeName(--> Str) is also { $!raw.name } 76 | method nodeType { $.type } 77 | method prefix { Str } 78 | method hasAttributes { False } 79 | method cloneNode is also { self.box: $!raw } 80 | 81 | # Inventory of unimplemented DOM methods. Mostly because W3C expects this 82 | # class to be based on a node, but LibXML doesn't. 83 | method nodeValue is also< 84 | parentNode childNodes firstChild lastChild previousSibling nextSibling 85 | attributes ownerDocument insertBefore insertAfter replaceChild removeChild 86 | appendChild hasChildNodes normalize isSupported namespaceURI> { 87 | die X::NYI.new 88 | } 89 | 90 | submethod DESTROY { $!raw.Free; } 91 | -------------------------------------------------------------------------------- /lib/LibXML/Raw/DOM/Attr.rakumod: -------------------------------------------------------------------------------- 1 | #| low level DOM. Works directly on Native XML Nodes 2 | unit role LibXML::Raw::DOM::Attr; 3 | my constant Attr = LibXML::Raw::DOM::Attr; 4 | use LibXML::Enums; 5 | use LibXML::Types :NCName, :QName; 6 | use NativeCall; 7 | 8 | method domAttrSerializeContent { ... } 9 | method doc { ... } 10 | method parent { ... } 11 | 12 | method isId { 13 | do with self.parent -> $parent { 14 | .IsID($parent, self) 15 | with self.doc; 16 | } // False; 17 | } 18 | 19 | method serializeContent { 20 | self.domAttrSerializeContent.Str; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /lib/LibXML/Raw/Defs.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Raw::Defs; 2 | 3 | our $XML2 is export(:XML2) = Rakudo::Internals.IS-WIN ?? find-library('libxml2') !! 'xml2'; 4 | our $BIND-XML2 is export(:BIND-XML2) = Rakudo::Internals.IS-WIN ?? find-library('xml6') !! %?RESOURCES; 5 | our $CLIB is export(:CLIB) = Rakudo::Internals.IS-WIN ?? 'msvcrt' !! Str; 6 | 7 | constant Opaque is export(:Opaque) = 'CPointer'; 8 | constant xmlCharP is export(:xmlCharP) = Str; 9 | my constant XML_XMLNS_NS is export(:XML_XMLNS_NS) = 'http://www.w3.org/2000/xmlns/'; 10 | my constant XML_XML_NS is export(:XML_XML_NS) = 'http://www.w3.org/XML/1998/namespace'; 11 | 12 | sub find-library($base) { 13 | # unmangle library names, so xml6.dll can load libxml.dll 14 | with %?RESOURCES{'libraries/' ~ $base} -> Distribution::Resource $file { 15 | my $tmpdir = $*SPEC.tmpdir ~ '/' ~ 'raku-libxml-' ~ $?DISTRIBUTION.meta; 16 | my $lib = $*VM.platform-library-name($base.IO); 17 | my IO() $dest = $tmpdir ~ '/' ~ $lib; 18 | { 19 | my $fh = $file.open; 20 | $fh.lock: :shared; 21 | unless $dest.e && $dest.s == $file.IO.s { 22 | # install it 23 | note "installing: " ~ $dest.Str; 24 | mkdir $tmpdir; 25 | $file.IO.copy($dest); 26 | } 27 | LEAVE $fh.close; 28 | } 29 | $dest; 30 | } 31 | else { 32 | $base 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/LibXML/Raw/Dict.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Raw::Dict; 2 | 3 | use NativeCall; 4 | use LibXML::Raw::Defs :$XML2, :Opaque; 5 | 6 | class xmlDict is repr(Opaque) is export { 7 | our sub New(--> xmlDict) is native($XML2) is symbol('xmlDictCreate') {*}; 8 | method Exists(Str, int32 --> Str) is native($XML2) is symbol('xmlDictExists') {*}; 9 | method Lookup(Str, int32 --> Str) is native($XML2) is symbol('xmlDictLookup') {*}; 10 | method Owns(Str --> int32) is native($XML2) is symbol('xmlDictOwns') {*}; 11 | method Size(--> int32) is native($XML2) is symbol('xmlDictSize') {*}; 12 | method Reference(--> int32) is native($XML2) is symbol('xmlDictReference') {*}; 13 | # only actually frees the dict when reference count is zero 14 | method Unreference is native($XML2) is symbol('xmlDictFree') {*}; 15 | method new(--> xmlDict:D) { New() } 16 | } 17 | -------------------------------------------------------------------------------- /lib/LibXML/Raw/HashTable.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Raw::HashTable; 2 | 3 | use NativeCall; 4 | use LibXML::Raw::Defs :$XML2, :$BIND-XML2, :Opaque, :xmlCharP; 5 | 6 | class xmlHashTable is repr(Opaque) is export { 7 | our sub New(int32 --> xmlHashTable) is native($XML2) is symbol('xmlHashCreate') {*} 8 | our sub DefaultDeallocator(Pointer, xmlCharP) is native($XML2) is symbol('xmlHashDefaultDeallocator') {*}; 9 | method new(UInt :$size = 256) { New($size) } 10 | method UpdateEntry(Str, Pointer, &deallocator ( Pointer, xmlCharP ) --> int32) is symbol('xmlHashUpdateEntry') is native($XML2) {*} 11 | method UpdateEntryNs(Str, Pointer, &deallocator ( Pointer, xmlCharP ) --> int32) is symbol('xml6_hash_update_entry_ns') is native($BIND-XML2) {*} 12 | method Lookup(Str --> Pointer) is symbol('xmlHashLookup') is native($XML2) {*} 13 | method LookupNs(Str --> Pointer) is symbol('xml6_hash_lookup_ns') is native($BIND-XML2) {*} 14 | method RemoveEntry(Str, &deallocator ( Pointer, xmlCharP ) --> int32) is symbol('xmlHashRemoveEntry') is native($XML2) {*} 15 | method RemoveEntryNs(Str, &deallocator ( Pointer, xmlCharP ) --> int32) is symbol('xml6_hash_remove_entry_ns') is native($BIND-XML2) {*} 16 | method Size(--> int32) is symbol('xmlHashSize') is native($XML2) {*} 17 | method Copy(&copier (Pointer, xmlCharP --> Pointer) --> xmlHashTable) is native($XML2) is symbol('xmlHashCopy') {*} 18 | method Free( &deallocator ( Pointer, xmlCharP ) ) is symbol('xmlHashFree') is native($XML2) {*} 19 | method Discard() is native($BIND-XML2) is symbol('xml6_hash_discard') {*} 20 | method keys(CArray[Pointer]) is native($BIND-XML2) is symbol('xml6_hash_keys') {*} 21 | method values(CArray[Pointer]) is native($BIND-XML2) is symbol('xml6_hash_values') {*} 22 | method key-values(CArray[Pointer]) is native($BIND-XML2) is symbol('xml6_hash_key_values') {*} 23 | method add-pairs(CArray, uint32, &deallocator ( Pointer, xmlCharP ) ) is native($BIND-XML2) is symbol('xml6_hash_add_pairs') {*} 24 | 25 | # build a two dimensional hash mapping element name to attribute names 26 | # specific to the multi-keyed Dtd attributes hash table 27 | method BuildDtdAttrDeclTable(--> xmlHashTable) is native($BIND-XML2) is symbol('xml6_hash_build_attr_decls') {*} 28 | } 29 | -------------------------------------------------------------------------------- /lib/LibXML/Raw/RelaxNG.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Raw::RelaxNG; 2 | 3 | use NativeCall; 4 | use LibXML::Raw; 5 | use LibXML::Raw::Defs :$XML2, :Opaque; 6 | 7 | class xmlRelaxNG is repr(Opaque) is export { 8 | method Free is symbol('xmlRelaxNGFree') is native($XML2) {*} 9 | } 10 | 11 | class xmlRelaxNGParserCtxt is repr(Opaque) is export { 12 | our sub NewUrl(Str:D --> xmlRelaxNGParserCtxt) is native($XML2) is symbol('xmlRelaxNGNewParserCtxt') {*} 13 | our sub NewMemory(Blob:D, int32 --> xmlRelaxNGParserCtxt) is native($XML2) is symbol('xmlRelaxNGNewMemParserCtxt') {*} 14 | our sub NewDoc(xmlDoc:D --> xmlRelaxNGParserCtxt) is native($XML2) is symbol('xmlRelaxNGNewDocParserCtxt') {*} 15 | method SetGenericErrorFunc( &err-func (xmlRelaxNGParserCtxt $ctx1, Str $msg1, Pointer), &warn-func (xmlRelaxNGParserCtxt $ctx2, Str $msg2, Pointer), Pointer $ctx) is native($XML2) is symbol('xmlRelaxNGSetParserErrors') {*} 16 | method SetParserErrorFunc( &error-func (xmlRelaxNGParserCtxt $, xmlError $)) is native($XML2) is symbol('xmlRelaxNGSetParserStructuredErrors') {*}; 17 | method SetStructuredErrorFunc( &error-func (xmlValidCtxt $, xmlError $)) is native($XML2) is symbol('xmlSetStructuredErrorFunc') {*}; 18 | method Parse(-->xmlRelaxNG) is native($XML2) is symbol('xmlRelaxNGParse') {*} 19 | method Free is symbol('xmlRelaxNGFreeParserCtxt') is native($XML2) {*} 20 | multi method new(Str:D :$url) { 21 | NewUrl($url); 22 | } 23 | multi method new( Blob() :$buf!, UInt :$bytes = $buf.bytes --> xmlRelaxNGParserCtxt:D) { 24 | NewMemory($buf, $bytes); 25 | } 26 | multi method new(xmlDoc:D :$doc!) { 27 | NewDoc($doc); 28 | } 29 | } 30 | 31 | class xmlRelaxNGValidCtxt is repr(Opaque) is export { 32 | our sub New(xmlRelaxNG:D --> xmlRelaxNGValidCtxt) is native($XML2) is symbol('xmlRelaxNGNewValidCtxt') {*} 33 | method SetStructuredErrorFunc( &error-func (xmlRelaxNGValidCtxt $, xmlError $)) is native($XML2) is symbol('xmlRelaxNGSetValidStructuredErrors') {*}; 34 | method ValidateDoc(xmlDoc:D --> int32) is native($XML2) is symbol('xmlRelaxNGValidateDoc') {*} 35 | method Free is symbol('xmlRelaxNGFreeValidCtxt') is native($XML2) {*} 36 | method new(xmlRelaxNG:D :$schema!) { 37 | New($schema); 38 | } 39 | } 40 | 41 | sub xmlRelaxNGInitTypes(--> int32) is native($XML2) {*} 42 | 43 | INIT { 44 | xmlRelaxNGInitTypes(); 45 | } 46 | -------------------------------------------------------------------------------- /lib/LibXML/Raw/Schema.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Raw::Schema; 2 | 3 | use NativeCall; 4 | use LibXML::Raw; 5 | use LibXML::Raw::Defs :$XML2, :Opaque; 6 | 7 | class xmlSchema is repr(Opaque) is export { 8 | method Free is symbol('xmlSchemaFree') is native($XML2) {*} 9 | } 10 | 11 | class xmlSchemaParserCtxt is repr(Opaque) is export { 12 | our sub NewUrl(Str:D --> xmlSchemaParserCtxt) is native($XML2) is symbol('xmlSchemaNewParserCtxt') {*} 13 | our sub NewMemory(Blob:D, int32 --> xmlSchemaParserCtxt) is native($XML2) is symbol('xmlSchemaNewMemParserCtxt') {*} 14 | our sub NewDoc(xmlDoc:D --> xmlSchemaParserCtxt) is native($XML2) is symbol('xmlSchemaNewDocParserCtxt') {*} 15 | method SetGenericErrorFunc( &err-func (xmlSchemaParserCtxt $ctx1, Str $msg1, Pointer), &warn-func (xmlSchemaParserCtxt $ctx2, Str $msg2, Pointer), Pointer $ctx) is native($XML2) is symbol('xmlSchemaSetParserErrors') {*} 16 | method SetParserErrorFunc( &error-func (xmlSchemaParserCtxt $, xmlError $)) is native($XML2) is symbol('xmlSchemaSetParserStructuredErrors') {*}; 17 | method SetStructuredErrorFunc( &error-func (xmlValidCtxt $, xmlError $)) is native($XML2) is symbol('xmlSetStructuredErrorFunc') {*}; 18 | method Parse(-->xmlSchema) is native($XML2) is symbol('xmlSchemaParse') {*} 19 | method Free is symbol('xmlSchemaFreeParserCtxt') is native($XML2) {*} 20 | multi method new(Str:D :$url) { 21 | NewUrl($url); 22 | } 23 | multi method new( Blob() :$buf!, UInt :$bytes = $buf.bytes --> xmlSchemaParserCtxt:D) { 24 | NewMemory($buf, $bytes); 25 | } 26 | multi method new(xmlDoc:D :$doc!) { 27 | NewDoc($doc); 28 | } 29 | } 30 | 31 | class xmlSchemaValidCtxt is repr(Opaque) is export { 32 | our sub New(xmlSchema:D --> xmlSchemaValidCtxt) is native($XML2) is symbol('xmlSchemaNewValidCtxt') {*} 33 | method SetStructuredErrorFunc( &error-func (xmlSchemaValidCtxt $, xmlError $)) is native($XML2) is symbol('xmlSchemaSetValidStructuredErrors') {*}; 34 | method ValidateDoc(xmlDoc:D --> int32) is native($XML2) is symbol('xmlSchemaValidateDoc') {*} 35 | method ValidateElement(xmlNode:D --> int32) is native($XML2) is symbol('xmlSchemaValidateOneElement') {*} 36 | method Free is symbol('xmlSchemaFreeValidCtxt') is native($XML2) {*} 37 | method new(xmlSchema:D :$schema!) { 38 | New($schema); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/LibXML/SAX.rakumod: -------------------------------------------------------------------------------- 1 | unit class LibXML::SAX; 2 | 3 | use LibXML::Parser; 4 | also is LibXML::Parser; 5 | 6 | use LibXML::SAX::Handler::SAX2; 7 | 8 | submethod TWEAK { 9 | self.sax-handler //= LibXML::SAX::Handler::SAX2; 10 | } 11 | 12 | -------------------------------------------------------------------------------- /lib/LibXML/SAX/Handler.rakumod: -------------------------------------------------------------------------------- 1 | 2 | class LibXML::SAX::Handler { 3 | use LibXML::SAX::Builder; 4 | use LibXML::Document; 5 | use LibXML::DocumentFragment; 6 | 7 | use LibXML::Raw; 8 | has xmlSAXHandler $.raw .= new; 9 | method native is DEPRECATED { $.raw } 10 | 11 | has &.serror-cb is rw; # structured errors 12 | has &.warning-cb is rw; # unstructured warnings 13 | has &.error-cb is rw; # unstructured errors 14 | has &.fatalError-cb is rw; # unstructured fatal errors 15 | 16 | has LibXML::SAX::Builder $.sax-builder; 17 | 18 | submethod TWEAK { 19 | $!sax-builder.build-sax-handler(self); 20 | } 21 | 22 | # Error Handling: 23 | # --------------- 24 | # The following are not directly dispatched via SAX. Rather they are 25 | # called from a LibXML::ErrorHandling installed SAX callback. 26 | multi method set-sax-callback('serror', &!serror-cb) {} 27 | multi method set-sax-callback('warning', &!warning-cb) {} 28 | multi method set-sax-callback('error', &!error-cb) {} 29 | multi method set-sax-callback('fatalError', &!fatalError-cb) {} 30 | 31 | # SAX Callbacks 32 | # ------------- 33 | # Remaining calls are all handled directly via a native SAX handler 34 | multi method set-sax-callback($name, &cb) is default { 35 | $!raw."$name"() = &cb; 36 | } 37 | 38 | multi method publish(LibXML::Document $doc!) { 39 | $doc; 40 | } 41 | multi method publish(LibXML::DocumentFragment $doc!) { 42 | $doc; 43 | } 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/LibXML/SAX/Handler/SAX2/Locator.rakumod: -------------------------------------------------------------------------------- 1 | class LibXML::SAX::Handler::SAX2::Locator { 2 | use LibXML::Raw; 3 | use Method::Also; 4 | has xmlSAXLocator $.raw .= default(); 5 | 6 | method getPublicId(xmlParserCtxt $ctx --> Str) { 7 | $!raw.getPublicId($ctx); 8 | } 9 | 10 | method getSystemId(xmlParserCtxt $ctx --> Str) { 11 | $!raw.getSystemId($ctx); 12 | } 13 | 14 | method getLineNumber(xmlParserCtxt $ctx --> UInt) is also { 15 | $!raw.getLineNumber($ctx); 16 | } 17 | 18 | method getColumnNumber(xmlParserCtxt $ctx --> UInt) is also { 19 | $!raw.getColumnNumber($ctx); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/LibXML/SAX/Handler/XML.rakumod: -------------------------------------------------------------------------------- 1 | #| Build pure Raku XML documents using LibXML's SAX parser 2 | class LibXML::SAX::Handler::XML { 3 | 4 | use LibXML::SAX::Handler::SAX2; 5 | also is LibXML::SAX::Handler::SAX2; 6 | 7 | # This class Builds a Raku 'XML' document, 8 | 9 | use XML::CDATA; 10 | use XML::Comment; 11 | use XML::Document; 12 | use XML::Element; 13 | use XML::PI; 14 | use XML::Text; 15 | use LibXML::SAX::Builder :sax-cb; 16 | 17 | has XML::Document $.doc is built; # The document that we're really building 18 | has XML::Node $!node; # Current node 19 | 20 | method publish($) { 21 | # ignore SAX created document; replace with our own 22 | $!doc; 23 | } 24 | 25 | method startDocument is sax-cb { 26 | $!doc .= new; 27 | $!node = $!doc; 28 | } 29 | 30 | method startElement($name, :%attribs) is sax-cb { 31 | my XML::Element $elem .= new: :$name, :%attribs; 32 | $!node.append: $elem; 33 | $!node = $elem; 34 | } 35 | 36 | method endElement(Str $name) is sax-cb { 37 | # step up the tree 38 | $!node = $!node.parent // Nil; 39 | } 40 | 41 | method cdataBlock(Str $data) is sax-cb { 42 | $!node.append: XML::CDATA.new(:$data); 43 | } 44 | 45 | method characters(Str $text) is sax-cb { 46 | $!node.append: XML::Text.new(:$text); 47 | } 48 | 49 | method comment(Str $text) is sax-cb { 50 | $!node.append: XML::Comment.new(:$text); 51 | } 52 | 53 | method processingInstruction(Str $target, Str $value) is sax-cb { 54 | my $data = $target ~ ' ' ~ $value; 55 | $!node.append: XML::PI.new(:$data); 56 | } 57 | 58 | } 59 | =begin pod 60 | 61 | =head2 Synopsis 62 | 63 | use LibXML; 64 | use LibXML::SAX::Handler::XML; 65 | use XML::Document; 66 | 67 | my LibXML::SAX::Handler::XML $sax-handler .= new; 68 | my XML::Document $doc = LibXML.parse: :file, :$sax-handler; 69 | 70 | =head2 Description 71 | 72 | L is a SAX handler that produce a pure Raku L 73 | object using the LIBXML SAX interface to parse the document. 74 | 75 | This class is an example of implementing a custom parser using the 76 | LibXML SAX interface, L and L. 77 | 78 | 79 | =end pod 80 | -------------------------------------------------------------------------------- /lib/LibXML/Threads.pod6: -------------------------------------------------------------------------------- 1 | =begin pod 2 | =head1 Notes on Raku LibXML Threading and Concurrency 3 | 4 | =head2 Concurrency and Parsing 5 | 6 | Parsing, including, validation and the Reader pull-parser can be run concurrently. 7 | 8 | =begin code :lang 9 | my @docs = @files.hyper.map: -> $file { LibXML::Parse: :$file } 10 | =end code 11 | 12 | However, the Raku LibXML bindings will protect these with a commonly library lock, defeating concurrency, if 13 | the libxml library has not been compiled with threading enabled. Threading can be 14 | checked using the L `threads` method. 15 | 16 | =for code :lang 17 | unless LibXML::Config.threads { ... } 18 | 19 | =head3 Concurrency and Input Callbacks 20 | 21 | Input callbacks may be set globally, without affecting concurrency. 22 | 23 | =begin code :lang 24 | my LibXML::InputCallback $input-callbacks .= new: @callbacks; 25 | LibXML::Config.input-callbacks = $input-callbacks; 26 | =end code 27 | 28 | They may also be set at the parser level. However, this is 29 | not thread safe. The LibXML library requires that you 30 | also enable the `parser-locking` flag, which limits 31 | concurrent parsing. 32 | 33 | =begin code :lang 34 | LibXML::Config.parser-locking = True; 35 | my LibXML::InputCallback $input-callbacks .= new: :callbacks{ 36 | :&match, :&read, :&open, :&close 37 | } 38 | LibXML::Config.parser-locking = True; 39 | my LibXML:D $parser .= new: :$input-callbacks; 40 | =end code 41 | 42 | =head2 DOM Concurrency 43 | 44 | =head3 Parallel Construction 45 | 46 | Document fragments and element sub-trees, may be constructed 47 | in parallel provided that they remain independent 48 | of each other. They then need to be assembled sequentially 49 | to create the final document: 50 | 51 | =begin code :lang 52 | my LibXML::Document $doc .= parse: :string(""); 53 | my @frags = @files.hyper.map: -> $file { LibXML::DocumentFragment.parse: :balanced, :$file} 54 | $doc.addChild($_) for @frags; 55 | =end code 56 | 57 | =head3 DOM Updates and Concurrency 58 | 59 | It is not thread-safe to read and modify DOM nodes concurrently. 60 | 61 | However, each node has a `protect` method that can be used to limit 62 | concurrency. 63 | 64 | =for code :lang 65 | $elem.protect: { $elem.appendChild: LibXML::Element.new('foo') } 66 | 67 | Be careful with nesting `protect` calls, to avoid potential deadlocks. 68 | =end pod -------------------------------------------------------------------------------- /lib/LibXML/Types.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Types; 2 | 3 | my token pident { 4 | <.ident> [ '-' [ \d+ <.ident>? || <.ident> ]* % '-' ]? 5 | } 6 | 7 | my token qname { 8 | ^ [ ':' ]? $ 9 | } 10 | 11 | subset NCName of Str is export(:NCName) where !.so || /^$/; 12 | subset QName of Str is export(:QName) where !.defined || $_ ~~ &qname; 13 | subset NameVal of Pair is export(:NameVal) where .key ~~ QName:D && .value ~~ Str:D; 14 | 15 | # XPathish is just a marker role for classes matching XPathRange 16 | role XPathish {} 17 | subset XPathRange is export(:XPathRange) where Bool|Numeric|Str|XPathish; 18 | 19 | # Another marker role to know that a class is LibXML::Item descendant 20 | role Itemish { } 21 | 22 | { 23 | my $resolution-cache = {}; 24 | our sub resolve-package(Str:D $pkg) is export(:resolve-package) is raw { 25 | (my $cache := ⚛$resolution-cache){$pkg}:exists 26 | ?? $cache{$pkg} 27 | !! resolve-package-slow-path($pkg) 28 | } 29 | 30 | sub add-to-cache(Str:D $pkg, Mu \result --> Mu) is raw { 31 | loop { 32 | # Another thread has already added this package, do nothing 33 | return result if (my $old-cache := ⚛$resolution-cache){$pkg}:exists; 34 | my $new-cache = $old-cache.clone; 35 | $new-cache{$pkg} := result; 36 | return result if cas($resolution-cache, $old-cache, $new-cache) === $old-cache; 37 | } 38 | } 39 | 40 | my &resolve-package-slow-path = $*RAKU.compiler.version >= v2022.04.74.g.1.c.4680544 41 | ?? anon sub resolve-package-slow-path(Str:D $pkg) is raw { 42 | my \found = do require ::($pkg); 43 | add-to-cache($pkg, found) 44 | } 45 | !! do { 46 | my $resolve-lock = Lock.new; 47 | anon sub resolve-package-slow-path(Str:D $pkg) is raw { 48 | my \found = $resolve-lock.protect: { do require ::($pkg) } 49 | add-to-cache($pkg, found) 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /lib/LibXML/Utils.rakumod: -------------------------------------------------------------------------------- 1 | unit module LibXML::Utils; 2 | use LibXML::Node::List; 3 | use LibXML::Node::Set; 4 | use LibXML::Raw; 5 | use LibXML::Enums; 6 | use LibXML::Config; 7 | 8 | sub output-options(UInt :$options is copy = 0, 9 | LibXML::Config :$config, 10 | Bool :$format, 11 | Bool :$skip-xml-declaration = $config.skip-xml-declaration, 12 | Bool :$tag-expansion = $config.tag-expansion, 13 | Bool :$html, 14 | # **DEPRECATED** 15 | Bool :$skip-decl, Bool :$expand, 16 | ) is export(:output-options) { 17 | 18 | warn ':skip-decl option is deprecated, please use :skip-xml-declaration' 19 | with $skip-decl; 20 | 21 | warn ':expand option is deprecated, please use :tag-expansion' 22 | with $expand; 23 | 24 | for $format => XML_SAVE_FORMAT, $skip-xml-declaration => XML_SAVE_NO_DECL, $tag-expansion => XML_SAVE_NO_EMPTY, $html => XML_SAVE_AS_HTML { 25 | $options +|= .value if .key; 26 | } 27 | 28 | $options; 29 | } 30 | -------------------------------------------------------------------------------- /lib/LibXML/X.rakumod: -------------------------------------------------------------------------------- 1 | use v6.d; 2 | 3 | role X::LibXML is Exception { } 4 | 5 | role X::LibXML::BadClass does X::LibXML { 6 | has Str:D $.class is required; 7 | has Str $.why; 8 | method message { 9 | "Bad LibXML $.what '$.class'" ~ |(": " ~ $_ with $.why) 10 | } 11 | } 12 | 13 | class X::LibXML::ClassName does X::LibXML::BadClass { 14 | has Str:D $.what = "class name"; 15 | } 16 | 17 | class X::LibXML::Class does X::LibXML::BadClass { 18 | has Str:D $.what = "type object"; 19 | } 20 | 21 | class X::LibXML::ArgumentType is X::TypeCheck does X::LibXML { 22 | has Str:D $.routine is required; 23 | method message { 24 | "Bad argument in call to $.routine: " ~ self.explain 25 | } 26 | } -------------------------------------------------------------------------------- /lib/LibXML/XInclude/Context.rakumod: -------------------------------------------------------------------------------- 1 | #| XInclude Processing Context 2 | unit class LibXML::XInclude::Context; 3 | 4 | use LibXML::_Configurable; 5 | also does LibXML::_Configurable; 6 | 7 | use LibXML::ErrorHandling; 8 | also does LibXML::ErrorHandling; 9 | 10 | use LibXML::_Options; 11 | use LibXML::Parser::Context; 12 | constant %Opts = %( 13 | %LibXML::Parser::Context::Opts, %(:config); 14 | ); 15 | also does LibXML::_Options[%Opts]; 16 | 17 | use NativeCall; 18 | 19 | =begin pod 20 | =head2 Synopsis 21 | 22 | use LibXML::XInclude::Context; 23 | my LibXML::XInclude::Context $xic .= new(); 24 | $xic.process-xincludes($doc); 25 | 26 | =head2 Description 27 | 28 | XInclude processing context. 29 | 30 | =end pod 31 | 32 | use LibXML::Config; 33 | use LibXML::Document; 34 | use LibXML::Raw; 35 | 36 | has LibXML::Document:D $.doc is required; 37 | has xmlXIncludeCtxt:D $.raw .= new: :doc($!doc.raw); 38 | has uint32 $.flags = self.config.parser-flags; 39 | 40 | # for the LibXML::ErrorHandling role 41 | has Bool ($.recover, $.suppress-errors, $.suppress-warnings) is rw; 42 | 43 | =head2 Methods 44 | 45 | 46 | submethod TWEAK(:raw($), *%opts) is hidden-from-backtrace { 47 | 48 | fail "This version of libxml ({self.config.version}) is too old to use XInclude contexts" 49 | unless self.config.version >= v2.13.00; 50 | 51 | $!raw.SetFlags($!flags); 52 | self.init-local-error-handling; 53 | } 54 | 55 | submethod DESTROY { 56 | .Free with $!raw; 57 | } 58 | 59 | multi method process-xincludes(::?CLASS:U: LibXML::Document:D :$doc!, *%opts --> Int) is hidden-from-backtrace { 60 | self.new(:$doc, |%opts).process-xincludes; 61 | } 62 | 63 | multi method process-xincludes(::?CLASS:D: LibXML::Element:D :$elem = $!doc.root --> Int) is hidden-from-backtrace { 64 | self.do: :$!raw, { 65 | $!raw.ProcessNode($elem.raw); 66 | } 67 | } 68 | 69 | =begin pod 70 | 71 | =head2 Copyright 72 | 73 | 2001-2007, AxKit.com Ltd. 74 | 75 | 2002-2006, Christian Glahn. 76 | 77 | 2006-2009, Petr Pajas. 78 | 79 | =head2 License 80 | 81 | This program is free software; you can redistribute it and/or modify it under 82 | the terms of the Artistic License 2.0 L. 83 | 84 | =end pod 85 | -------------------------------------------------------------------------------- /lib/LibXML/XPath/Expression.rakumod: -------------------------------------------------------------------------------- 1 | #| Interface to LibXML pre-compiled XPath Expressions 2 | unit class LibXML::XPath::Expression; 3 | 4 | use LibXML::Raw; 5 | use Method::Also; 6 | 7 | has xmlXPathCompExpr $!raw; 8 | method raw { $!raw } 9 | 10 | submethod TWEAK(Str:D :$expr!) { 11 | $!raw .= new(:$expr); 12 | die "invalid xpath expression: $expr" 13 | without $!raw; 14 | } 15 | submethod DESTROY { 16 | .Free with $!raw; 17 | } 18 | 19 | method compile(Str:D $expr) is also { 20 | self.new: :$expr; 21 | } 22 | 23 | =begin pod 24 | =head2 Synopsis 25 | 26 | use LibXML::XPath::Expression; 27 | my LibXML::XPath::Expression $compiled-xpath .= compile('//foo[@bar="baz"][position()<4]'); 28 | 29 | # interface from LibXML::Node 30 | 31 | my $result = $node.find($compiled-xpath); 32 | my @nodes = $node.findnodes($compiled-xpath); 33 | my $value = $node.findvalue($compiled-xpath); 34 | 35 | # interface from LibXML::XPath::Context 36 | 37 | my $result = $xpc.find($compiled-xpath, $node); 38 | my @nodes = $xpc.findnodes($compiled-xpath, $node); 39 | my $value = $xpc.findvalue($compiled-xpath, $node); 40 | 41 | my LibXML::XPath::Expression $compiled .= new: :expr($xpath-string), :$node; 42 | 43 | =head2 Description 44 | 45 | This is a Raku interface to libxml2's pre-compiled XPath expressions. 46 | Pre-compiling an XPath expression can give in some performance benefit if the 47 | same XPath query is evaluated many times. C<<<<<>>>>> objects can be passed to all C<<<<<>>>>> functions in L that expect an XPath expression. 48 | 49 | =head2 Methods 50 | 51 | =head3 method new 52 | 53 | method new( 54 | Str :expr($xpath)!, LibXML::Node :node($ref-node) 55 | ) returns LibXML::XPath::Expression 56 | 57 | The constructor takes an XPath 1.0 expression as a string and returns an object 58 | representing the pre-compiled expressions (the actual data structure is 59 | internal to libxml2). 60 | 61 | =head3 method compile 62 | 63 | method compile( 64 | Str $xpath, 65 | LibXML::Node :node($ref-node) 66 | ) returns LibXML::XPath::Expression; 67 | 68 | Alternative constructor which takes a positional XPath expression as a string. 69 | 70 | 71 | =head2 Copyright 72 | 73 | 2001-2007, AxKit.com Ltd. 74 | 75 | 2002-2006, Christian Glahn. 76 | 77 | 2006-2009, Petr Pajas. 78 | 79 | =head2 License 80 | 81 | This program is free software; you can redistribute it and/or modify it under 82 | the terms of the Artistic License 2.0 L. 83 | 84 | =end pod 85 | -------------------------------------------------------------------------------- /lib/LibXML/XPath/Object.rakumod: -------------------------------------------------------------------------------- 1 | use v6; 2 | unit class LibXML::XPath::Object; 3 | 4 | use LibXML::Item; 5 | use LibXML::Raw; 6 | use LibXML::Types :XPathRange; 7 | use LibXML::_Configurable; 8 | use LibXML::_Collection; 9 | use NativeCall; 10 | 11 | also does LibXML::Types::XPathish; 12 | also does LibXML::_Configurable; 13 | also does LibXML::_Collection; 14 | 15 | has xmlXPathObject:D $.raw is required; 16 | 17 | submethod TWEAK { $!raw.Reference } 18 | 19 | submethod DESTROY { $!raw.Unreference } 20 | 21 | method coerce-to-raw(XPathRange $content is copy) { 22 | xmlXPathObject($content ~~ LibXML::Types::XPathish ?? $content.raw !! $content) 23 | } 24 | 25 | multi method COERCE(XPathRange:D $content) { 26 | self.create: raw => self.coerce-to-raw($content) 27 | } 28 | 29 | method coerce($v) is DEPRECATED { self.COERCE: $v } 30 | 31 | method value(xmlXPathObject :$raw = $.raw, Bool :$literal, *%c --> XPathRange) { 32 | given $raw.value { 33 | when xmlNodeSet { 34 | given self.iterate-set(LibXML::Item, .copy) { 35 | $literal ?? .to-literal !! $_; 36 | } 37 | } 38 | when anyNode { 39 | $literal ?? .Str !! LibXML::Item.box: $_, |%c; 40 | } 41 | default { $_ } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /lib/LibXML/_Collection.rakumod: -------------------------------------------------------------------------------- 1 | use v6.d; 2 | unit role LibXML::_Collection; 3 | 4 | use LibXML::_Configurable; 5 | use LibXML::Config; 6 | use LibXML::Raw; 7 | use LibXML::Types :resolve-package; 8 | 9 | method create(|) {...} 10 | 11 | my class NOT-YET { } 12 | 13 | my $NODE-SET = NOT-YET; 14 | my $NODE-LIST = NOT-YET; 15 | 16 | method iterate-set($of, xmlNodeSet $raw, Bool :$deref) is implementation-detail { 17 | cas $NODE-SET, { resolve-package('LibXML::Node::Set') } if $NODE-SET === NOT-YET; 18 | # iterate through a set of nodes 19 | self.create: $NODE-SET, :$raw, :$of, :$deref 20 | } 21 | 22 | method iterate-list($of, Bool :$blank = True) is implementation-detail { 23 | cas $NODE-LIST, { resolve-package('LibXML::Node::List') } if $NODE-LIST === NOT-YET; 24 | # follow a chain of .next links. 25 | self.create: $NODE-LIST, :$of, :$blank, :parent(self); 26 | } 27 | 28 | -------------------------------------------------------------------------------- /lib/LibXML/_Configurable.rakumod: -------------------------------------------------------------------------------- 1 | use v6.d; 2 | unit role LibXML::_Configurable; 3 | use LibXML::Config; 4 | 5 | has LibXML::Config:D $!config is built handles = LibXML::Config.global; 6 | 7 | proto method config(|) {*} 8 | multi method config(::?CLASS:U:) { LibXML::Config.global } 9 | multi method config(::?CLASS:D:) { $!config } 10 | 11 | proto method create(|) {*} 12 | multi method create(::?CLASS:U: \kind, |c) { 13 | kind.new: |c 14 | } 15 | multi method create(::?CLASS:D: \kind, |c) { 16 | kind.new: :$!config, |c 17 | } 18 | multi method create(::?ROLE:D :from(:$for)! is raw, |c) { 19 | self.WHAT.new: :config($for.config), |c 20 | } 21 | 22 | multi method box(LibXML::_Configurable \kind, |c) { 23 | kind.box: :$!config, |c 24 | } 25 | -------------------------------------------------------------------------------- /lib/LibXML/_DomNode.rakumod: -------------------------------------------------------------------------------- 1 | unit role LibXML::_DomNode; 2 | 3 | method getNamespaceURI {...} 4 | method localname {...} 5 | method name {...} 6 | method string-value {...} 7 | method Str {...} 8 | method type {...} 9 | method value {...} 10 | method ast {...} 11 | method box {...} 12 | 13 | -------------------------------------------------------------------------------- /lib/LibXML/_ParentNode.rakumod: -------------------------------------------------------------------------------- 1 | #| methods common to elements, documents and document fragments 2 | unit role LibXML::_ParentNode; 3 | 4 | use LibXML::Node; 5 | use LibXML::Config; 6 | use LibXML::Enums; 7 | use LibXML::Types :QName, :NameVal; 8 | 9 | method iterate-set(|) {...} 10 | 11 | method getElementsByTagName(Str:D $name) is raw { 12 | self.iterate-set(self.box-class(XML_ELEMENT_NODE), $.raw.getElementsByTagName($name)); 13 | } 14 | method getElementsByLocalName(Str:D $name) { 15 | self.iterate-set(self.box-class(XML_ELEMENT_NODE), $.raw.getElementsByLocalName($name)); 16 | } 17 | method getElementsByTagNameNS(Str $uri, Str $name) { 18 | self.iterate-set(self.box-class(XML_ELEMENT_NODE), $.raw.getElementsByTagNameNS($uri, $name)); 19 | } 20 | method getChildrenByLocalName(Str:D $name) { 21 | self.iterate-set(LibXML::Item, $.raw.getChildrenByLocalName($name)); 22 | } 23 | method getChildrenByTagName(Str:D $name) { 24 | self.iterate-set(LibXML::Node, $.raw.getChildrenByTagName($name)); 25 | } 26 | method getChildrenByTagNameNS(Str:D $uri, Str:D $name) { 27 | self.iterate-set(LibXML::Node, $.raw.getChildrenByTagNameNS($uri, $name)); 28 | } 29 | method elements { 30 | self.iterate-set(self.box-class(XML_ELEMENT_NODE), $.raw.getChildrenByLocalName('*')); 31 | } 32 | 33 | #| adds a child element with tag $name and text content $value 34 | multi method appendTextChild(QName:D $name, Str $value? --> LibXML::Node) { 35 | self.box: $.raw.appendTextChild($name, $value); 36 | } 37 | 38 | multi method appendTextChild(NameVal:D $_) { 39 | $.appendTextChild(.key, .value); 40 | } 41 | 42 | method ast(LibXML::Config :$config, Bool :$blank = $config.keep-blanks --> Pair) { 43 | self.ast-key => [self.childNodes(:$blank).map(*.ast: :$blank)]; 44 | } 45 | -------------------------------------------------------------------------------- /lib/LibXML/_Rawish.rakumod: -------------------------------------------------------------------------------- 1 | use v6.d; 2 | unit role LibXML::_Rawish[::RawType, *@handles]; 3 | 4 | # Pre-cache attribute object. Since role body is invoked for each role consumption we'd have 5 | # exactly one copy per class. 6 | my $attr := ::?CLASS.^attributes.grep('$!raw').head; 7 | 8 | # Similarly, pre-cache attribute value. This makes sense **only** if immutability of $.raw is guaranteed. 9 | has RawType $!_raw = $attr.get_value(self); 10 | 11 | # We cannot apply `handles` directly on _raw because @handles are not known at compile time. 12 | # But we can take advantage of the fact that role body is executed when role is getting specialized. 13 | 14 | for @handles -> $handles { 15 | my &delegate = anon method (|c) is raw is hidden-from-backtrace { 16 | (self.defined ?? $!_raw !! RawType)."$handles"(|c) 17 | } 18 | &delegate.set_name($handles); 19 | ::?CLASS.^add_method($handles, &delegate); 20 | } 21 | 22 | # Ensure that .raw on each LibXML::Node descendant class reports the right raw type 23 | multi method raw(::?CLASS:U:) { RawType } -------------------------------------------------------------------------------- /lib/LibXML/_Validator.rakumod: -------------------------------------------------------------------------------- 1 | #| abstract validation role. Performed by LibXML::{Dtd|Schema|RelaxNG} 2 | unit role LibXML::_Validator; 3 | 4 | method validate {...} 5 | method is-valid {...} 6 | -------------------------------------------------------------------------------- /resources/libraries/README.windows: -------------------------------------------------------------------------------- 1 | Windows Support 2 | ---------------- 3 | 4 | There isn't an automatic procedure yet for building the 5 | LibXML library (libxml2.dll) or bindings (xml6.dll). 6 | 7 | So this needs to be done by hand on occasions to upgrade 8 | the library and/or bindings. 9 | 10 | Furthermore, we're currently building without iconv, 11 | which restricts us to a small number of XML encoding schemes. 12 | 13 | Building on Windows 14 | ------------------- 15 | This is a minimal build of libxml2 and xml6 (binding) DLLs, 16 | without iconv for Unicode support. 17 | 18 | From a Rakudo Powershell (running as administrator): 19 | 20 | 0. Install chocolatey - see https://chocolatey.org/install 21 | 22 | 1. Ensure that git, the mingw make system and compilers are installed: 23 | 24 | choco install make mingw git 25 | 26 | 2. Here's how I built it: 27 | 28 | cd LibXML-raku 29 | cd .. 30 | git clone https:://github.com/GNOME/libxml2; # mirror 31 | cd libxml2\win32\ 32 | cscript.exe configure.js compiler=mingw threads=yes iconv=no 33 | make -f Makefile.mingw libxml 34 | cd ..\..\LibXML-raku 35 | cp ..\libxml2\win32\bin.mingw32\libxml2.dll resources\libraries\ 36 | rm resources\libraries\xml6.dll 37 | raku Build.pm6 -I ..\libxml2\include\ 38 | git add -f resources\libraries\xml6.dll resources\libraries\libxml2.dll 39 | git commit -m"..." -------------------------------------------------------------------------------- /resources/libraries/liblibxml2.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/resources/libraries/liblibxml2.dylib -------------------------------------------------------------------------------- /resources/libraries/liblibxml2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/resources/libraries/liblibxml2.so -------------------------------------------------------------------------------- /resources/libraries/libxml2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/resources/libraries/libxml2.dll -------------------------------------------------------------------------------- /resources/libraries/xml6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/resources/libraries/xml6.dll -------------------------------------------------------------------------------- /samples/ProductCatalog.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 21 | 22 | 23 | 28 | 29 | 30 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /samples/article.xml: -------------------------------------------------------------------------------- 1 |
2 | Something here 3 | 12345 4 | 2001-04-01 5 | XML.com 6 |
Foo
7 |
Bar
8 |
Barry
9 |
Zzzzz
10 | Here's some leading text 11 | And here is the rest... 12 |
13 | -------------------------------------------------------------------------------- /samples/article_bad.xml: -------------------------------------------------------------------------------- 1 |
2 | Something here 3 | 12345 4 | XML.com 5 |
Foo
6 | Here's some leading text 7 | And here is the rest... 8 |
9 | -------------------------------------------------------------------------------- /samples/article_external_bad.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | Something here 4 | 12345 5 | 2001-04-01 6 | XML.com 7 |
Foo
8 | Here's some leading text 9 | And here is the rest... 10 |
11 | -------------------------------------------------------------------------------- /samples/article_internal_bad.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ]> 18 |
19 | Something here 20 | 12345 21 | 2001-04-01 22 | XML.com 23 |
Foo
24 | Here's some leading text 25 | And here is the rest... 26 |
27 | -------------------------------------------------------------------------------- /samples/bad.dtd: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /samples/bad.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/catalog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/cdata.xml: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /samples/complex/complex.dtd: -------------------------------------------------------------------------------- 1 | 2 | %f; 3 | -------------------------------------------------------------------------------- /samples/complex/complex.xml: -------------------------------------------------------------------------------- 1 | 3 | %e; 4 | ]> 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/complex/complex2.xml: -------------------------------------------------------------------------------- 1 | 2 | &foo; 3 | 4 | -------------------------------------------------------------------------------- /samples/complex/dtd/f.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | %g; 4 | -------------------------------------------------------------------------------- /samples/complex/dtd/g.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /samples/dromeds.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1 or 2 5 | Cranky 6 | 7 | 8 | 1 (sort of) 9 | Aloof 10 | 11 | 12 | (see Llama) 13 | Friendly 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/dtd.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | ]> 8 | This is a valid document &foo; ! 9 | -------------------------------------------------------------------------------- /samples/enc2_latin2.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/samples/enc2_latin2.html -------------------------------------------------------------------------------- /samples/enc_latin2.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/samples/enc_latin2.html -------------------------------------------------------------------------------- /samples/ext_ent.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /samples/ns.xml: -------------------------------------------------------------------------------- 1 | 2 | Camelid 3 | 4 4 | 5 | -------------------------------------------------------------------------------- /samples/test.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | test 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/test2.xml: -------------------------------------------------------------------------------- 1 | .. -------------------------------------------------------------------------------- /samples/test3.xml: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/test4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | test 4 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/utf-16-1.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/samples/utf-16-1.html -------------------------------------------------------------------------------- /samples/utf-16-2.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/samples/utf-16-2.html -------------------------------------------------------------------------------- /samples/utf-16-2.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/samples/utf-16-2.xml -------------------------------------------------------------------------------- /samples/xmlns/badguy.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/xmlns/goodguy.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sparrow.yaml: -------------------------------------------------------------------------------- 1 | image: 2 | - melezhik/sparrow:debian_arm 3 | - melezhik/sparrow:ubuntu_arm 4 | # - melezhik/sparrow:archlinux 5 | tasks: 6 | - 7 | name: main 8 | default: true 9 | language: Bash 10 | code: | 11 | raku --version 12 | zef --version 13 | 14 | cd source/ 15 | 16 | zef install . --deps-only --test-depends --build-depends --/test 17 | zef build . 18 | zef test . --verbose 19 | 20 | depends: 21 | - 22 | name: install-deps 23 | - 24 | name: install-deps 25 | language: Bash 26 | code: | 27 | if test $os = "debian"; then 28 | sudo apt-get update 29 | sudo apt-get install -y libxml2-dev libxslt-dev 30 | elif test $os = "ubuntu"; then 31 | sudo apt-get update 32 | sudo apt-get install -y libxml2-dev libxslt-dev 33 | elif test $os = "arch"; then 34 | sudo pacman -S --needed --noconfirm -q libxml2 libxslt 35 | fi 36 | -------------------------------------------------------------------------------- /src/domXPath.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBXML_DOM_XPATH_H__ 2 | #define __LIBXML_DOM_XPATH_H__ 3 | 4 | #include 5 | #include 6 | #include "xml6.h" 7 | 8 | DLLEXPORT void 9 | perlDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs); 10 | 11 | DLLEXPORT xmlNodeSetPtr 12 | domXPathGetNodeSet(xmlXPathObjectPtr, int select); 13 | 14 | DLLEXPORT xmlXPathObjectPtr 15 | domXPathNewPoint(xmlNodePtr node, int); 16 | 17 | DLLEXPORT xmlNodeSetPtr 18 | domXPathSelectStr( xmlNodePtr refNode, xmlChar* xpathstring ); 19 | 20 | DLLEXPORT xmlNodeSetPtr 21 | domXPathSelect( xmlNodePtr refNode, xmlXPathCompExprPtr comp ); 22 | 23 | DLLEXPORT xmlNodePtr 24 | domXPathCtxtSetNode(xmlXPathContextPtr, xmlNodePtr); 25 | 26 | DLLEXPORT xmlXPathContextPtr 27 | domXPathNewCtxt(xmlNodePtr refNode); 28 | 29 | DLLEXPORT void 30 | domSetXPathCtxtErrorHandler(xmlXPathContextPtr, xmlStructuredErrorFunc); 31 | 32 | DLLEXPORT void 33 | domXPathFreeCtxt(xmlXPathContextPtr); 34 | 35 | xmlXPathObjectPtr 36 | domXPathFind( xmlNodePtr refNode, xmlXPathCompExprPtr comp, int to_bool ); 37 | 38 | xmlXPathObjectPtr 39 | domXPathFindCtxt( xmlXPathContextPtr ctxt, xmlXPathCompExprPtr comp, xmlNodePtr refNode, int to_bool ); 40 | 41 | DLLEXPORT void 42 | domReferenceNodeSet(xmlNodeSetPtr self); 43 | 44 | DLLEXPORT void 45 | domUnreferenceNodeSet(xmlNodeSetPtr self); 46 | 47 | DLLEXPORT xmlNodePtr 48 | domNodeSetAtPos(xmlNodeSetPtr self, int i); 49 | 50 | DLLEXPORT void domPushNodeSet(xmlNodeSetPtr self, xmlNodePtr elem, int reference); 51 | 52 | DLLEXPORT xmlNodeSetPtr domCreateNodeSetFromList(xmlNodePtr elem, int keep_blanks); 53 | 54 | DLLEXPORT xmlNodePtr domPopNodeSet(xmlNodeSetPtr self); 55 | 56 | DLLEXPORT int domDeleteNodeSetItem(xmlNodeSetPtr self, xmlNodePtr item); 57 | 58 | DLLEXPORT xmlNodeSetPtr domCopyNodeSet(xmlNodeSetPtr); 59 | 60 | DLLEXPORT xmlNodeSetPtr domReverseNodeSet(xmlNodeSetPtr); 61 | 62 | DLLEXPORT xmlNodeSetPtr domXPathSelectCtxt(xmlXPathContextPtr, xmlXPathCompExprPtr, xmlNodePtr refNode); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/xml6.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_H 2 | #define __XML6_H 3 | 4 | #ifdef _WIN32 5 | #define DLLEXPORT __declspec(dllexport) 6 | #else 7 | #define DLLEXPORT extern 8 | #endif 9 | 10 | #define xml6_warn(msg) fprintf(stderr, __FILE__ ":%d: %s\n", __LINE__, (msg)); 11 | 12 | #endif /* __XML6_H */ 13 | -------------------------------------------------------------------------------- /src/xml6_config.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_config.h" 3 | #include "libxml/xmlversion.h" 4 | 5 | DLLEXPORT int xml6_config_have_libxml_reader(void) { 6 | #ifdef LIBXML_READER_ENABLED 7 | return 1; 8 | #else 9 | return 0; 10 | #endif 11 | } 12 | 13 | DLLEXPORT int xml6_config_have_libxml_writer(void) { 14 | #ifdef LIBXML_WRITER_ENABLED 15 | return 1; 16 | #else 17 | return 0; 18 | #endif 19 | } 20 | 21 | DLLEXPORT int xml6_config_have_threads(void) { 22 | #ifdef LIBXML_THREAD_ENABLED 23 | return 1; 24 | #else 25 | return 0; 26 | #endif 27 | } 28 | 29 | DLLEXPORT int xml6_config_have_compression(void) { 30 | #ifdef LIBXML_ZLIB_ENABLED 31 | return 1; 32 | #else 33 | return 0; 34 | #endif 35 | } 36 | 37 | DLLEXPORT int xml6_config_have_iconv(void) { 38 | #ifdef LIBXML_ICONV_ENABLED 39 | return 1; 40 | #else 41 | return 0; 42 | #endif 43 | } 44 | 45 | DLLEXPORT char* xml6_config_version(void) { 46 | return LIBXML_DOTTED_VERSION; 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/xml6_config.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_CONFIG_H 2 | #define __XML6_CONFIG_H 3 | 4 | #include 5 | 6 | DLLEXPORT int xml6_config_have_libxml_reader(void); 7 | DLLEXPORT int xml6_config_have_libxml_writer(void); 8 | DLLEXPORT int xml6_config_have_threads(void); 9 | DLLEXPORT int xml6_config_have_compression(void); 10 | DLLEXPORT int xml6_config_have_iconv(void); 11 | DLLEXPORT char* xml6_config_version(void); 12 | 13 | #endif /* __XML6_CONFIG_H */ 14 | -------------------------------------------------------------------------------- /src/xml6_doc.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_doc.h" 3 | #include "xml6_ref.h" 4 | #include 5 | #include 6 | 7 | DLLEXPORT void xml6_doc_set_encoding(xmlDocPtr self, char *encoding) { 8 | assert(self != NULL); 9 | 10 | if ( self->encoding != NULL ) { 11 | xmlFree( (xmlChar*) self->encoding ); 12 | } 13 | 14 | if (encoding != NULL && strlen(encoding)) { 15 | self->encoding = xmlStrdup( (const xmlChar *) encoding ); 16 | } else { 17 | self->encoding = NULL; 18 | } 19 | } 20 | 21 | DLLEXPORT void xml6_doc_set_URI(xmlDocPtr self, char *URI) { 22 | assert(self != NULL); 23 | if (self->URL) xmlFree((xmlChar*) self->URL); 24 | self->URL = URI ? xmlStrdup((const xmlChar*) URI) : NULL; 25 | } 26 | 27 | DLLEXPORT void xml6_doc_set_version(xmlDocPtr self, char *version) { 28 | assert(self != NULL); 29 | if (self->version) xmlFree((xmlChar*) self->version); 30 | self->version = version ? xmlStrdup((const xmlChar*) version) : NULL; 31 | } 32 | 33 | DLLEXPORT int 34 | xml6_doc_set_flags(xmlDocPtr self, int flags) { 35 | assert(self != NULL); 36 | assert(self->_private != NULL); 37 | return xml6_ref_set_flags( self->_private, flags); 38 | } 39 | 40 | DLLEXPORT int 41 | xml6_doc_get_flags(xmlDocPtr self) { 42 | assert(self != NULL); 43 | assert(self->_private != NULL); 44 | return xml6_ref_get_flags( self->_private); 45 | } 46 | 47 | -------------------------------------------------------------------------------- /src/xml6_doc.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_DOC_H 2 | #define __XML6_DOC_H 3 | 4 | #include 5 | 6 | DLLEXPORT void xml6_doc_set_encoding(xmlDocPtr, char* enc); 7 | DLLEXPORT void xml6_doc_set_URI(xmlDocPtr, char* URI) ; 8 | DLLEXPORT void xml6_doc_set_version(xmlDocPtr, char*); 9 | DLLEXPORT int xml6_doc_set_flags(xmlDocPtr, int); 10 | DLLEXPORT int xml6_doc_get_flags(xmlDocPtr); 11 | 12 | #endif /* __XML6_DOC_H */ 13 | -------------------------------------------------------------------------------- /src/xml6_entity.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_entity.h" 3 | #include 4 | #include 5 | 6 | 7 | DLLEXPORT xmlEntityPtr 8 | xml6_entity_create(const xmlChar *name, int type, 9 | const xmlChar *ExternalID, const xmlChar *SystemID, 10 | const xmlChar *content) { 11 | xmlEntityPtr rv; 12 | 13 | rv = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity)); 14 | if (rv == NULL) { 15 | xml6_warn("xml6_entity_create: xmlMalloc failed"); 16 | return(NULL); 17 | } 18 | memset(rv, 0, sizeof(xmlEntity)); 19 | rv->type = XML_ENTITY_DECL; 20 | 21 | /* 22 | * fill the structure. 23 | */ 24 | rv->etype = (xmlEntityType) type; 25 | rv->name = xmlStrdup(name); 26 | if (ExternalID != NULL) 27 | rv->ExternalID = xmlStrdup(ExternalID); 28 | if (SystemID != NULL) 29 | rv->SystemID = xmlStrdup(SystemID); 30 | 31 | if (content != NULL) { 32 | rv->length = xmlStrlen(content); 33 | rv->content = xmlStrndup(content, rv->length); 34 | } else { 35 | rv->length = 0; 36 | rv->content = NULL; 37 | } 38 | 39 | rv->URI = NULL; 40 | rv->orig = NULL; 41 | rv->owner = 0; 42 | 43 | return(rv); 44 | } 45 | -------------------------------------------------------------------------------- /src/xml6_entity.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_ENTITY_H 2 | #define __XML6_ENTITY_H 3 | 4 | #include 5 | 6 | DLLEXPORT xmlEntityPtr 7 | xml6_entity_create(const xmlChar *name, int type, 8 | const xmlChar *ExternalID, const xmlChar *SystemID, 9 | const xmlChar *content); 10 | 11 | #endif /* __XML6_ENTITY_H */ 12 | -------------------------------------------------------------------------------- /src/xml6_entity.rakumod: -------------------------------------------------------------------------------- 1 | ## untested. Just for fun 2 | use NativeCall; 3 | use LibXML::Enums; 4 | use LibXML::Raw; 5 | use LibXML::Raw::Defs :xmlCharP; 6 | 7 | sub xml6_warn($) {...} 8 | sub xmlMalloc($, $) {...} 9 | sub xmlStrlen($, $) {...} 10 | sub xmlStrndup($,$) {...} 11 | 12 | sub xml6_entity_create(xmlCharP $name, int32 $type, 13 | xmlCharP $ExternalID, xmlCharP $SystemID, 14 | xmlCharP $content --> xmlEntity) { 15 | my xmlEntity $rv; 16 | 17 | $rv = xmlMalloc(nativesizeof(xmlEntity)) // do { 18 | xml6_warn("xml6_entity_create: malloc failed"); 19 | return(xmlEntity); 20 | } 21 | xmlEntity.memset; 22 | $rv.type = XML_ENTITY_DECL; 23 | $rv.checked = 0; 24 | 25 | # 26 | # fill the structure. 27 | # 28 | $rv.etype = $type; 29 | $rv.name .= &xmlStrdup; 30 | $rv.ExternalID = xmlStrdup($_) 31 | with $ExternalID; 32 | $rv.SystemID = xmlStrdup($_) 33 | with $SystemID; 34 | 35 | with $content { 36 | $rv.length = .&xmlStrlen; 37 | $rv.content = .&xmlStrndup($rv.length); 38 | } else { 39 | $rv.length = 0; 40 | $rv.content = Nil; 41 | } 42 | 43 | $rv.URI = Nil; 44 | $rv.orig = Nil; 45 | $rv.owner = 0; 46 | 47 | $rv; 48 | } 49 | -------------------------------------------------------------------------------- /src/xml6_error.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_error.h" 3 | #include 4 | 5 | DLLEXPORT xmlChar* 6 | xml6_error_context_and_column(xmlErrorPtr self, unsigned int* column) { 7 | xmlParserInputPtr input; 8 | const xmlChar *cur, *base, *col_cur; 9 | unsigned int n, col; 10 | xmlChar content[81]; /* space for 80 chars + null terminator */ 11 | xmlChar *ctnt; 12 | int domain = self->domain; 13 | xmlParserCtxtPtr ctxt = NULL; 14 | 15 | if ((domain == XML_FROM_PARSER) || (domain == XML_FROM_HTML) || 16 | (domain == XML_FROM_DTD) || (domain == XML_FROM_NAMESPACE) || 17 | (domain == XML_FROM_IO) || (domain == XML_FROM_VALID)) { 18 | ctxt = (xmlParserCtxtPtr) self->ctxt; 19 | } 20 | if (ctxt == NULL) { 21 | return NULL; 22 | } 23 | input = ctxt->input; 24 | if ((input != NULL) && (input->filename == NULL) && 25 | (ctxt->inputNr > 1)) { 26 | input = ctxt->inputTab[ctxt->inputNr - 2]; 27 | } 28 | if (input == NULL) { 29 | return NULL; 30 | } 31 | cur = input->cur; 32 | base = input->base; 33 | /* skip backwards over any end-of-lines */ 34 | while ((cur > base) && ((*(cur) == '\n') || (*(cur) == '\r'))) { 35 | cur--; 36 | } 37 | n = 0; 38 | /* search backwards for beginning-of-line (to max buff size) */ 39 | while ((n++ < (sizeof(content)-1)) && (cur > base) && 40 | (*(cur) != '\n') && (*(cur) != '\r')) 41 | cur--; 42 | /* search backwards for beginning-of-line for calculating the 43 | * column. */ 44 | col_cur = cur; 45 | while ((col_cur > base) && (*(col_cur) != '\n') && (*(col_cur) != '\r')) 46 | col_cur--; 47 | if ((*(cur) == '\n') || (*(cur) == '\r')) cur++; 48 | if ((*(col_cur) == '\n') || (*(col_cur) == '\r')) col_cur++; 49 | /* calculate the error position in terms of the current position */ 50 | col = input->cur - col_cur; 51 | /* search forward for end-of-line (to max buff size) */ 52 | n = 0; 53 | ctnt = content; 54 | /* copy selected text to our buffer */ 55 | while ((*cur != 0) && (*(cur) != '\n') && 56 | (*(cur) != '\r') && (n < sizeof(content)-1)) { 57 | *ctnt++ = *cur++; 58 | n++; 59 | } 60 | *ctnt = 0; 61 | *column = col; 62 | return xmlStrdup(content); 63 | } 64 | -------------------------------------------------------------------------------- /src/xml6_error.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_ERROR_H 2 | #define __XML6_ERROR_H 3 | 4 | #include 5 | #include 6 | 7 | DLLEXPORT xmlChar* 8 | xml6_error_context_and_column(xmlErrorPtr, unsigned int*); 9 | 10 | #endif /* __XML6_ERROR_H */ 11 | -------------------------------------------------------------------------------- /src/xml6_gbl.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_GBL_H 2 | #define __XML6_GBL_H 3 | 4 | #include 5 | #include 6 | 7 | #if LIBXML_VERSION < 21300 8 | # define XML6_GBL_COMPAT_OLD_ERRORS 1 9 | #endif 10 | 11 | #if LIBXML_VERSION < 21400 12 | # define XML6_GBL_COMPAT_KEEP_BLANKS 1 13 | #endif 14 | 15 | DLLEXPORT void xml6_gbl_init(void); 16 | 17 | DLLEXPORT void* xml6_gbl_get_external_entity_loader(void); 18 | DLLEXPORT void xml6_gbl_set_external_entity_loader(void *); 19 | DLLEXPORT int xml6_gbl_set_external_entity_loader_net(int); 20 | 21 | DLLEXPORT int xml6_gbl_os_thread_get_tag_expansion(void); 22 | DLLEXPORT void xml6_gbl_os_thread_set_tag_expansion(int); 23 | 24 | DLLEXPORT int xml6_gbl_os_thread_get_keep_blanks(void); 25 | DLLEXPORT void xml6_gbl_os_thread_set_keep_blanks(int flag); 26 | 27 | DLLEXPORT void xml6_gbl_os_thread_xml_free(void*); 28 | 29 | typedef void (*xml6_gbl_MessageCallback) (const char *msg); 30 | DLLEXPORT xmlError* xml6_gbl_os_thread_get_last_error(void); 31 | DLLEXPORT void* xml6_gbl_save_error_handlers(void); 32 | DLLEXPORT void xml6_gbl_restore_error_handlers(void*); 33 | DLLEXPORT void xml6_gbl_set_generic_error_handler(xml6_gbl_MessageCallback, void (*route)(void*, xmlGenericErrorFunc)); 34 | 35 | DLLEXPORT xmlSAXLocatorPtr xml6_gbl_os_thread_get_default_sax_locator(void); 36 | 37 | DLLEXPORT const xmlChar* xml6_gbl_dict(xmlChar*); 38 | DLLEXPORT const xmlChar* xml6_gbl_dict_dup(const xmlChar* word); 39 | DLLEXPORT int xml6_gbl_dict_size(void); 40 | 41 | #endif /* __XML6_GBL_H */ 42 | -------------------------------------------------------------------------------- /src/xml6_hash.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_HASH_H 2 | #define __XML6_HASH_H 3 | 4 | #include 5 | 6 | DLLEXPORT void xml6_hash_keys(xmlHashTablePtr, void**); 7 | DLLEXPORT void xml6_hash_values(xmlHashTablePtr, void**); 8 | DLLEXPORT void xml6_hash_key_values(xmlHashTablePtr, void**); 9 | DLLEXPORT int xml6_hash_update_entry_ns(xmlHashTablePtr, xmlChar*, void*, xmlHashDeallocator); 10 | DLLEXPORT int xml6_hash_remove_entry_ns(xmlHashTablePtr, xmlChar*, xmlHashDeallocator); 11 | DLLEXPORT void xml6_hash_add_pairs(xmlHashTablePtr, void**, unsigned int, xmlHashDeallocator); 12 | DLLEXPORT xmlHashTablePtr xml6_hash_xpath_node_children(xmlNodePtr, int); 13 | DLLEXPORT xmlHashTablePtr xml6_hash_xpath_nodeset(xmlNodeSetPtr, int); 14 | DLLEXPORT xmlHashTablePtr xml6_hash_build_attr_decls(xmlHashTablePtr); 15 | DLLEXPORT void* xml6_hash_lookup_ns(xmlHashTablePtr, xmlChar*); 16 | DLLEXPORT void xml6_hash_discard(xmlHashTablePtr); 17 | 18 | #endif /* __XML6_HASH_H */ 19 | -------------------------------------------------------------------------------- /src/xml6_input.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_input.h" 3 | #include 4 | 5 | DLLEXPORT void xml6_input_set_filename(xmlParserInputPtr self, char *url) { 6 | assert(self != NULL); 7 | if (self->filename) xmlFree((xmlChar*)self->filename); 8 | self->filename = (char*) xmlStrdup((const xmlChar *) url); 9 | } 10 | 11 | DLLEXPORT int xml6_input_buffer_push_str(xmlParserInputBufferPtr buffer, const xmlChar* str) { 12 | xmlChar* new_string = NULL; 13 | int len; 14 | 15 | assert(buffer != NULL); 16 | assert(str != NULL); 17 | 18 | new_string = xmlStrdup(str); 19 | len = xmlStrlen(new_string); 20 | 21 | return xmlParserInputBufferPush(buffer, len, (const char*)new_string); 22 | } 23 | -------------------------------------------------------------------------------- /src/xml6_input.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_INPUT_H 2 | #define __XML6_INPUT_H 3 | 4 | #include 5 | #include 6 | 7 | DLLEXPORT void xml6_input_set_filename(xmlParserInputPtr, char *url); 8 | 9 | DLLEXPORT int xml6_input_buffer_push_str(xmlParserInputBufferPtr, const xmlChar* str); 10 | 11 | #endif /* __XML6_INPUT_H */ 12 | -------------------------------------------------------------------------------- /src/xml6_node.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_NODE_H 2 | #define __XML6_NODE_H 3 | 4 | #include 5 | #include "libxml/xpath.h" 6 | #include "libxml/c14n.h" 7 | 8 | DLLEXPORT void xml6_node_add_reference(xmlNodePtr); 9 | DLLEXPORT int xml6_node_remove_reference(xmlNodePtr); 10 | DLLEXPORT int xml6_node_lock(xmlNodePtr); 11 | DLLEXPORT int xml6_node_unlock(xmlNodePtr); 12 | 13 | DLLEXPORT xmlNodePtr xml6_node_find_root(xmlNodePtr); 14 | DLLEXPORT xmlNodePtr xml6_node_first_child(xmlNodePtr, int); 15 | DLLEXPORT xmlNodePtr xml6_node_last_child(xmlNodePtr, int); 16 | DLLEXPORT xmlNodePtr xml6_node_next(xmlNodePtr, int); 17 | DLLEXPORT xmlNodePtr xml6_node_prev(xmlNodePtr, int); 18 | DLLEXPORT void xml6_node_set_doc(xmlNodePtr, xmlDocPtr); 19 | DLLEXPORT void xml6_node_set_ns(xmlNodePtr, xmlNsPtr); 20 | DLLEXPORT void xml6_node_set_nsDef(xmlNodePtr, xmlNsPtr); 21 | DLLEXPORT void xml6_node_set_content(xmlNodePtr, const xmlChar*); 22 | DLLEXPORT int xml6_node_is_htmlish(xmlNodePtr); 23 | DLLEXPORT xmlChar* xml6_node_to_buf(xmlNodePtr, int, size_t*, char*); 24 | DLLEXPORT xmlChar* xml6_node_to_str_C14N(xmlNodePtr, int, xmlC14NMode, xmlChar**, xmlNodeSetPtr); 25 | DLLEXPORT int xml6_node_get_size(int); 26 | DLLEXPORT int xml6_node_get_elem_index(xmlNodePtr); 27 | 28 | #endif /* __XML6_NODE_H */ 29 | -------------------------------------------------------------------------------- /src/xml6_notation.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_notation.h" 3 | #include "xml6_ref.h" 4 | #include 5 | #include 6 | 7 | DLLEXPORT xmlNotationPtr xml6_notation_copy(xmlNotationPtr self) { 8 | xmlNotationPtr new = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation)); 9 | 10 | assert(self != NULL); 11 | assert(new != NULL); 12 | 13 | memset(new, 0, sizeof(xmlNotation)); 14 | 15 | if (self->name != NULL) 16 | new->name = xmlStrdup(self->name); 17 | if (self->SystemID != NULL) 18 | new->SystemID = xmlStrdup(self->SystemID); 19 | if (self->PublicID != NULL) 20 | new->PublicID = xmlStrdup(self->PublicID); 21 | return new; 22 | } 23 | 24 | DLLEXPORT xmlChar* xml6_notation_unique_key(xmlNotationPtr self) { 25 | xmlChar *rv = NULL; 26 | 27 | if (self == NULL) { 28 | rv = xmlStrdup((xmlChar*)"||"); 29 | } 30 | else { 31 | if (self->name != NULL) rv = xmlStrdup(self->name); 32 | rv = xmlStrcat(rv, (const xmlChar *) "|"); 33 | if (self->PublicID != NULL) rv = xmlStrdup(self->PublicID); 34 | rv = xmlStrcat(rv, (const xmlChar *) "|"); 35 | if (self->SystemID != NULL) rv = xmlStrcat(rv, self->SystemID); 36 | } 37 | 38 | return rv; 39 | } 40 | 41 | DLLEXPORT xmlNotationPtr 42 | xml6_notation_create(const xmlChar *name, const xmlChar *PublicID, const xmlChar *SystemID) { 43 | xmlNotationPtr self = (xmlNotationPtr) xmlMalloc(sizeof(xmlNotation)); 44 | memset(self, 0, sizeof(xmlNotation)); 45 | self->name = xmlStrdup(name); 46 | if (SystemID != NULL) 47 | self->SystemID = xmlStrdup(SystemID); 48 | if (PublicID != NULL) 49 | self->PublicID = xmlStrdup(PublicID); 50 | return self; 51 | } 52 | 53 | DLLEXPORT void 54 | xml6_notation_free(xmlNotationPtr self) { 55 | if (self == NULL) return; 56 | if (self->name != NULL) 57 | xmlFree((xmlChar *) self->name); 58 | if (self->PublicID != NULL) 59 | xmlFree((xmlChar *) self->PublicID); 60 | if (self->SystemID != NULL) 61 | xmlFree((xmlChar *) self->SystemID); 62 | xmlFree(self); 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/xml6_notation.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_NOTATION_H 2 | #define __XML6_NOTATION_H 3 | 4 | #include 5 | 6 | DLLEXPORT xmlNotationPtr xml6_notation_copy(xmlNotationPtr); 7 | DLLEXPORT xmlChar* xml6_notation_unique_key(xmlNotationPtr); 8 | DLLEXPORT xmlNotationPtr xml6_notation_create(const xmlChar*, const xmlChar*, const xmlChar*); 9 | DLLEXPORT void xml_notation_free(xmlNotationPtr); 10 | #endif /* __XML6_NOTATION_H */ 11 | -------------------------------------------------------------------------------- /src/xml6_ns.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_gbl.h" 3 | #include "xml6_ns.h" 4 | #include "xml6_ref.h" 5 | #include 6 | #include 7 | 8 | DLLEXPORT xmlNsPtr xml6_ns_copy(xmlNsPtr self) { 9 | xmlNsPtr new = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); 10 | 11 | assert(self != NULL); 12 | assert(new != NULL); 13 | 14 | memset(new, 0, sizeof(xmlNs)); 15 | new->type = self->type; 16 | 17 | if (self->href != NULL) 18 | new->href = xmlStrdup(self->href); 19 | if (self->prefix != NULL) 20 | new->prefix = xmlStrdup(self->prefix); 21 | return new; 22 | } 23 | 24 | DLLEXPORT const xmlChar* xml6_ns_unique_key(xmlNsPtr self) { 25 | xmlChar *rv = NULL; 26 | 27 | assert(self != NULL); 28 | 29 | if (self->prefix != NULL) rv = xmlStrdup(self->prefix); 30 | rv = xmlStrcat(rv, (const xmlChar *) "|"); 31 | if (self->href != NULL) rv = xmlStrcat(rv, self->href); 32 | return xml6_gbl_dict(rv); 33 | } 34 | -------------------------------------------------------------------------------- /src/xml6_ns.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_NS_H 2 | #define __XML6_NS_H 3 | 4 | #include 5 | 6 | DLLEXPORT xmlNsPtr xml6_ns_copy(xmlNsPtr); 7 | DLLEXPORT const xmlChar* xml6_ns_unique_key(xmlNsPtr); 8 | 9 | #endif /* __XML6_NS_H */ 10 | -------------------------------------------------------------------------------- /src/xml6_parser_ctx.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_PARSER_CTX_H 2 | #define __XML6_PARSER_CTX_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | DLLEXPORT void xml6_parser_ctx_add_reference(xmlParserCtxtPtr); 9 | DLLEXPORT int xml6_parser_ctx_remove_reference(xmlParserCtxtPtr); 10 | DLLEXPORT void xml6_parser_ctx_set_sax(xmlParserCtxtPtr, xmlSAXHandlerPtr); 11 | DLLEXPORT void xml6_parser_ctx_set_myDoc(xmlParserCtxtPtr, xmlDocPtr); 12 | DLLEXPORT htmlParserCtxtPtr xml6_parser_ctx_html_create_str(const xmlChar*, const char*); 13 | DLLEXPORT htmlParserCtxtPtr xml6_parser_ctx_html_create_buf(const xmlChar*, int, const char*); 14 | DLLEXPORT xmlParserInputPtr xml_parser_ctx_load_dtd(xmlParserCtxtPtr, const xmlChar*, const xmlChar*); 15 | DLLEXPORT int xml6_parser_ctx_close(xmlParserCtxtPtr); 16 | 17 | #endif /* __XML6_PARSER_CTX_H */ 18 | -------------------------------------------------------------------------------- /src/xml6_reader.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_READER_H 2 | #define __XML6_READER_H 3 | 4 | #include "xml6.h" 5 | #include 6 | #include 7 | 8 | DLLEXPORT int 9 | xml6_reader_next_sibling(xmlTextReaderPtr self); 10 | 11 | DLLEXPORT int 12 | xml6_reader_next_element(xmlTextReaderPtr self, char *, char *); 13 | 14 | DLLEXPORT int 15 | xml6_reader_next_sibling_element(xmlTextReaderPtr self, char *name, char *URI); 16 | 17 | DLLEXPORT int 18 | xml6_reader_skip_siblings(xmlTextReaderPtr self); 19 | 20 | DLLEXPORT int 21 | xml6_reader_finish(xmlTextReaderPtr self); 22 | 23 | DLLEXPORT int 24 | xml6_reader_next_pattern_match(xmlTextReaderPtr self, xmlPatternPtr compiled) ; 25 | 26 | #endif /* __XML6_READER_H */ 27 | -------------------------------------------------------------------------------- /src/xml6_ref.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_REF_H 2 | #define __XML6_REF_H 3 | 4 | #include "xml6.h" 5 | #include 6 | 7 | #define XML6_REF_MAGIC 2020437046 // 'xml6', little endian 8 | #define XML6_FAIL(self, msg) { self && self->_private ? xml6_ref_set_fail(self->_private, (xmlChar*)msg) : xml6_warn(msg); return NULL;} 9 | #define XML6_FAIL_i(self, msg) {self && self->_private ? xml6_ref_set_fail(self->_private, (xmlChar*)msg) : xml6_warn(msg); return -1;} 10 | 11 | DLLEXPORT void xml6_ref_add(void**); 12 | DLLEXPORT int xml6_ref_remove(void**, const char*, void*); 13 | DLLEXPORT void xml6_ref_set_fail(void*, xmlChar*); 14 | DLLEXPORT xmlChar* xml6_ref_get_fail(void*); 15 | DLLEXPORT int xml6_ref_set_flags(void*, int); 16 | DLLEXPORT int xml6_ref_get_flags(void*); 17 | DLLEXPORT int xml6_ref_lock(void*); 18 | DLLEXPORT int xml6_ref_unlock(void*); 19 | DLLEXPORT void* xml6_ref_freed(); 20 | DLLEXPORT int xml6_ref_count(void); 21 | 22 | #endif /* __XML6_REF_H */ 23 | -------------------------------------------------------------------------------- /src/xml6_xpath.c: -------------------------------------------------------------------------------- 1 | #include "xml6.h" 2 | #include "xml6_xpath.h" 3 | #include "xml6_ref.h" 4 | #include 5 | 6 | DLLEXPORT void 7 | xml6_xpath_object_add_reference(xmlXPathObjectPtr self) { 8 | assert(self != NULL); 9 | xml6_ref_add( &(self->user2) ); 10 | } 11 | 12 | DLLEXPORT int 13 | xml6_xpath_object_is_referenced(xmlXPathObjectPtr self) { 14 | return (self != NULL && self->user2 != NULL ); 15 | } 16 | 17 | DLLEXPORT int 18 | xml6_xpath_object_remove_reference(xmlXPathObjectPtr self) { 19 | return xml6_ref_remove( &(self->user2), "xpath object", (void*) self ); 20 | } 21 | 22 | DLLEXPORT xmlNodePtr 23 | xml6_xpath_ctxt_set_node(xmlXPathContextPtr ctxt, xmlNodePtr node) { 24 | if (node != NULL) { 25 | if (ctxt->doc != node->doc) 26 | XML6_FAIL(node, "changing XPathContext between documents is not supported"); 27 | } 28 | else { 29 | node = (xmlNodePtr) ctxt->doc; 30 | } 31 | 32 | ctxt->node = node; 33 | 34 | return node; 35 | } 36 | 37 | DLLEXPORT xmlXPathVariableLookupFunc 38 | xml6_xpath_ctxt_get_var_lookup_func(xmlXPathContextPtr ctxt) { 39 | if (ctxt) { 40 | return ctxt->varLookupFunc; 41 | } 42 | else { 43 | return NULL; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/xml6_xpath.h: -------------------------------------------------------------------------------- 1 | #ifndef __XML6_XPATH_H 2 | #define __XML6_XPATH_H 3 | 4 | #include 5 | 6 | #include "xml6.h" 7 | 8 | DLLEXPORT void xml6_xpath_object_add_reference(xmlXPathObjectPtr); 9 | DLLEXPORT int xml6_xpath_object_is_referenced(xmlXPathObjectPtr); 10 | DLLEXPORT int xml6_xpath_object_remove_reference(xmlXPathObjectPtr); 11 | DLLEXPORT xmlNodePtr xml6_xpath_ctxt_set_node(xmlXPathContextPtr, xmlNodePtr node); 12 | DLLEXPORT xmlXPathVariableLookupFunc xml6_xpath_ctxt_get_var_lookup_func(xmlXPathContextPtr); 13 | 14 | #endif /* __XML6_XPATH_H */ 15 | -------------------------------------------------------------------------------- /t/000sanity.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | 4 | use LibXML::Raw::Defs :$XML2, :$BIND-XML2, :$CLIB; 5 | use NativeCall; 6 | 7 | # some sanity checking on our native library configuration. 8 | # Check a few symbols $XML2, $BIND-XML2 and $CLIB libraries. 9 | # Useful test when doing porting work on META6.json, LibXML::Raw::Defs etc 10 | 11 | # sanity check our libraries 12 | sub xmlInitParser is native($XML2) {*} 13 | lives-ok {xmlInitParser()}, 'can call xmlInitParser()'; 14 | 15 | ok $BIND-XML2.IO.s, $BIND-XML2.IO.path ~ ' library has been built'; 16 | unless $BIND-XML2.IO.s { 17 | bail-out "unable to access {$BIND-XML2.basename}, has it been built, (e.g. 'zef build .' or 'raku Build.rakumod'" ~ ('Makefile'.IO.e ?? ", or 'make'" !! '') ~ ')'; 18 | } 19 | 20 | lives-ok({ cglobal($BIND-XML2, "xml6_config_version", Pointer) }, 'binding lib sanity') 21 | or note "unable to access 'xml6' binding library; has it been built? (e.g. 'zef build .)"; 22 | 23 | for { 24 | ok(try {cglobal($BIND-XML2, $_, Pointer)}, "binding lib $_ symbol") 25 | or diag "error fetching $_ symbol: $!"; 26 | } 27 | 28 | for { 29 | ok(try {cglobal($XML2, $_, Pointer)}, "libxml $_ binding") 30 | or diag "error fetching $_ symbol: $!"; 31 | } 32 | 33 | for { 34 | ok(try {cglobal($CLIB, $_, Pointer)}, "clib $_ binding") 35 | or diag "error fetching $_ symbol: $!"; 36 | } 37 | 38 | done-testing(); 39 | -------------------------------------------------------------------------------- /t/00dict.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use LibXML::Dict; 3 | use Test; 4 | plan 12; 5 | 6 | my LibXML::Dict $dict .= new; 7 | 8 | is $dict.elems, 0, 'dict initial size'; 9 | $dict = 'a'; 10 | $dict.see('b'); 11 | $dict.see: ; 12 | 13 | is $dict.elems, 4, 'dict updated size'; 14 | 15 | ok $dict:exists; 16 | nok $dict:exists; 17 | nok $dict:exists; 18 | ok $dict:exists; 19 | 20 | is $dict, 'a'; 21 | is-deeply $dict, Str; 22 | is-deeply $dict, Str; 23 | 24 | my $e = 'e'; 25 | dies-ok {$dict := $e}; 26 | is $dict.elems, 4, 'dict updated size'; 27 | 28 | $dict = $e; 29 | is $dict.elems, 5, 'dict updated size'; 30 | 31 | -------------------------------------------------------------------------------- /t/00dom-w3c.t: -------------------------------------------------------------------------------- 1 | use LibXML; 2 | use W3C::DOM::Test; 3 | W3C::DOM::Test::document-basic(LibXML); 4 | -------------------------------------------------------------------------------- /t/00errors.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML::XPath::Context; 4 | use LibXML::Config; 5 | plan 4; 6 | 7 | # Silence warnings 8 | LibXML::XPath::Context.SetGenericErrorFunc(-> |c { }) 9 | unless LibXML::Config.version >= v2.13.00; 10 | 11 | { 12 | use LibXML::Pattern; 13 | my LibXML::Pattern $patt; 14 | 15 | lives-ok {$patt.new(:pattern('a'))}; 16 | throws-like { $patt.new(:pattern('a[zz')) }, X::LibXML::OpFail, :message('XML Pattern Compile operation failed'); 17 | } 18 | 19 | { 20 | use LibXML::RegExp; 21 | my LibXML::RegExp $regexp; 22 | 23 | lives-ok {$regexp.new(:regexp('a'))}; 24 | throws-like { $regexp.new(:regexp('a[zz')) }, X::LibXML::OpFail, :message('XML RegExp Compile operation failed'); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /t/00hash-object.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML::HashMap; 4 | use LibXML::Element; 5 | use LibXML::Enums; 6 | use LibXML::Config; 7 | use LibXML::Types :XPathRange; 8 | use NativeCall; 9 | 10 | plan 2; 11 | 12 | subtest 'node-hash' => { 13 | plan 4; 14 | my $config = LibXML::Config.new; 15 | my LibXML::HashMap[LibXML::Element] $elems .= new(:$config); 16 | 17 | for 1 .. 5 { 18 | $elems{'e'~$_} .= new('Elem' ~ $_, :$config); 19 | } 20 | 21 | is-deeply [$elems.keys.sort], [(1..5).map('e'~*)], 'keys'; 22 | is-deeply [$elems.values.map(*.Str).sort], [(1..5).map({''})], 'values'; 23 | 24 | $elems:delete; 25 | nok $elems:exists, 'deleted element'; 26 | $elems .= new('Replaced', :$config); 27 | is $elems.Str, '', 'replaced element'; 28 | } 29 | 30 | subtest 'object-hash' => { 31 | plan 20; 32 | 33 | my $config = LibXML::Config.new; 34 | my LibXML::HashMap[XPathRange] $h .= new(:$config); 35 | is-deeply $h.of, XPathRange; 36 | is $h.elems, 0; 37 | lives-ok { $h = 'Hi';}; 38 | is $h.elems, 1; 39 | is $h, 'Hi'; 40 | is-deeply $h, XPathRange; 41 | lives-ok {$h = 'Again'}; 42 | is $h.elems, 1; 43 | is $h, 'Again'; 44 | $h:delete; 45 | is $h, XPathRange; 46 | is $h.elems, 0; 47 | $h = 42; 48 | is-deeply $h, 42e0; 49 | is-deeply $h, 42e0; 50 | $h = "xx"; 51 | 52 | is-deeply $h.keys.sort, ("Xx", "x:y"); 53 | is-deeply $h.values.sort, (42e0, "xx"); 54 | is-deeply $h.pairs.sort, (Xx => 42e0, 'x:y' => "xx"); 55 | 56 | my LibXML::Element $node .= new('test', :$config); 57 | 58 | lives-ok {$h = $node;}; 59 | is-deeply $h.keys.sort, ("Xx", "elem", "x:y"); 60 | ok $node.isSame($h); 61 | ok $h.isSame($node); 62 | } 63 | 64 | done-testing; 65 | -------------------------------------------------------------------------------- /t/00hash-type.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML::HashMap; 4 | use LibXML::Element; 5 | use LibXML::Document; 6 | use LibXML::Node::Set; 7 | use LibXML::Config; 8 | use NativeCall; 9 | 10 | plan 4; 11 | 12 | subtest 'Str HashMaps' => { 13 | plan 17; 14 | my LibXML::HashMap[Str] $h .= new; 15 | is-deeply $h.of, Str; 16 | is $h.elems, 0; 17 | lives-ok {$h = 'Hi'}; 18 | is $h.elems, 1; 19 | is $h, 'Hi'; 20 | is-deeply $h, Str; 21 | lives-ok {$h = 'Again'}; 22 | is $h.elems, 1; 23 | is $h, 'Again'; 24 | $h:delete; 25 | is $h, Str; 26 | is $h.elems, 0; 27 | $h = 42; 28 | is-deeply $h, '42'; 29 | $h = "xx"; 30 | 31 | is-deeply $h.keys.sort, ("Xx", "yy"); 32 | is-deeply $h.values.sort, ("42", "xx"); 33 | is-deeply $h.pairs.sort, (Xx => "42", yy => "xx"); 34 | 35 | my CArray[Str] $pairs .= new("a", "A", "b", "B"); 36 | my LibXML::HashMap[Str] $h1 .= new: :$pairs; 37 | is-deeply $h1.pairs.sort, (a => "A", b => "B"); 38 | is-deeply $h1.kv.sort, ("A", "B", "a", "b"); 39 | } 40 | 41 | subtest 'Int HashMaps' => { 42 | plan 3; 43 | my LibXML::HashMap[Int] $h .= new; 44 | is-deeply $h.of, Int; 45 | $h = 42; 46 | is-deeply $h, 42; 47 | is-deeply $h.kv, ("Xx", 42); 48 | } 49 | 50 | my LibXML::Element $node .= new('test'); 51 | 52 | subtest 'LibXML::Item HashMaps' => { 53 | plan 3; 54 | my LibXML::HashMap[LibXML::Element] $h .= new; 55 | 56 | lives-ok {$h = $node}; 57 | is-deeply $h.keys, ("elem", ); 58 | ok $node.isSame($h.kv[1]); 59 | } 60 | 61 | subtest 'LibXML::Node::Set HashMaps' => { 62 | plan 4; 63 | my LibXML::HashMap[LibXML::Node::Set] $h .= new; 64 | my LibXML::Node::Set $set .= new; 65 | $set.add: $node; 66 | lives-ok {$h = $set}; 67 | isa-ok $h.of, LibXML::Node::Set; 68 | is-deeply $h.keys, ("elem", ); 69 | ok $node.isSame($h.kv[1][0]); 70 | } 71 | 72 | done-testing; 73 | -------------------------------------------------------------------------------- /t/00input-callback.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | 4 | # bootstrapping tests for Input callbacks 5 | 6 | use NativeCall; 7 | use LibXML; 8 | use LibXML::InputCallback; 9 | use LibXML::Config; 10 | 11 | plan 19; 12 | 13 | my $fh; 14 | my %seen; 15 | 16 | my LibXML::InputCallback $input-callbacks .= new: :callbacks{ 17 | :match(sub ($f) {%seen++; return $f.IO.e }), 18 | :open(sub ($f) {%seen++; $f.IO.open(:r) }), 19 | :read(sub ($fh, $bytes) {%seen++; $fh.read($bytes)}), 20 | :close(sub ($fh) {%seen++; $fh.close;}), 21 | }; 22 | 23 | # low level callback checks on external API 24 | my ($context) = $input-callbacks.make-contexts; 25 | my $match = ($context.match)("samples/test2.xml"); 26 | is-deeply $match, 1, "match callback when found"; 27 | $match = ($context.match)("samples/does-not-exist.xml"); 28 | is-deeply $match, 0, "match callback when not found"; 29 | my $ptr := ($context.open)("samples/test2.xml"); 30 | isa-ok $ptr, Pointer, 'open returns a pointer'; 31 | my ($handle, @guff) = $context.handles.values; 32 | ok ($handle.defined && !@guff), 'Exactly one open handle'; 33 | isa-ok $handle.fh, IO::Handle, '$handle.fh'; 34 | my CArray[uint8] $buf .= new(0 xx 5); 35 | my $n = ($context.read)($ptr, $buf, $buf.elems); 36 | is $n, 5, 'read callback return value'; 37 | is $buf.map(*.chr).join, '', 'return read buffer'; 38 | $n = ($context.close)($ptr); 39 | is $n, 0, 'close callback return value'; 40 | ok !$context.handles, 'No longer have an open fh'; 41 | check-seen(); 42 | 43 | LibXML::Config.input-callbacks = $input-callbacks; 44 | 45 | my $parser = LibXML.new; 46 | 47 | $parser.expand-xinclude = True; 48 | 49 | my $dom; 50 | lives-ok {$dom = $parser.parse: :file("samples/test.xml")}, 'file parse'; 51 | check-seen(); 52 | is $dom.documentElement.firstChild.name, '#text', 'DOM sanity'; 53 | 54 | done-testing; 55 | 56 | sub check-seen { 57 | ok %seen, 'match callback called'; 58 | ok %seen, 'open callback called'; 59 | ok %seen, 'read callback called'; 60 | ok %seen, 'close callback called'; 61 | %seen = (); 62 | } 63 | -------------------------------------------------------------------------------- /t/00native.t: -------------------------------------------------------------------------------- 1 | use Test; 2 | use LibXML::Raw; 3 | use LibXML::Enums; 4 | use LibXML::Raw::Defs :$BIND-XML2; 5 | use NativeCall; 6 | 7 | sub node-size(int32 $type --> int32) is symbol('xml6_node_get_size') is native($BIND-XML2) {*} 8 | 9 | my @ClassMap := @LibXML::Raw::ClassMap; 10 | 11 | plan +@ClassMap; 12 | 13 | isa-ok anyNode.new, Failure, 'anyNode.new fails'; 14 | 15 | for 1 ..^ @ClassMap -> $type { 16 | my $class := @ClassMap[$type]; 17 | if $class ~~ anyNode|xmlNs { 18 | todo "has known size changes between libxml2 versions" 19 | if $type == XML_ENTITY_DECL|XML_ATTRIBUTE_NODE; 20 | is node-size($type), nativesizeof($class), 'size of ' ~ $class.raku; 21 | } 22 | else { 23 | skip "class $type"; 24 | } 25 | } -------------------------------------------------------------------------------- /t/00query-selectors.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::Document; 5 | use LibXML::Node; 6 | use LibXML::Node::Set; 7 | 8 | class dummySelectorHandler { 9 | # one hard-coded rule adapted from the CSS::Selector::To::XPath test suite 10 | method query-to-xpath('li.bar') {"//li[contains(concat(' ', normalize-space(@class), ' '), ' bar ')]"} 11 | } 12 | 13 | my LibXML::Document $doc = LibXML.parse: :string(q:to<\_(ツ)_/>); 14 | 19 | \_(ツ)_/ 20 | 21 | my $xpath-context = $doc.xpath-context; 22 | 23 | dies-ok {$xpath-context.querySelector('li.bar')}, 'query selection before configuration - dies'; 24 | 25 | my List $expected = ('
  • baz
  • ', 26 | '
  • baz
  • '); 27 | 28 | $xpath-context.query-handler = dummySelectorHandler.new; 29 | 30 | my LibXML::Node:D $node = $xpath-context.querySelector('li.bar'); 31 | is $node.Str, $expected[0]; 32 | 33 | my LibXML::Node::Set:D $node-set = $xpath-context.querySelectorAll('li.bar'); 34 | is $node-set.map(*.Str), $expected; 35 | 36 | done-testing(); 37 | 38 | -------------------------------------------------------------------------------- /t/00with-cache.t: -------------------------------------------------------------------------------- 1 | use Test; 2 | use LibXML::Document; 3 | use LibXML::Config; 4 | 5 | plan 4; 6 | 7 | my $xml = q:to; 8 | 9 | 10 | Some text 11 | 12 | XML 13 | 14 | my LibXML::Document $doc-uncached .= parse: :string($xml), :!blanks; 15 | 16 | my LibXML::Config $config .= new: :with-cache; 17 | ok $config.with-cache; 18 | 19 | my LibXML::Document $doc-cached .= parse: :string($xml), :$config, :!blanks; 20 | 21 | subtest 'without caching', { 22 | nok $doc-uncached.config.with-cache; 23 | my @nodes1 = $doc-uncached.root.children; 24 | my @nodes2 = $doc-uncached.root.children; 25 | nok $doc-uncached.root === $doc-uncached.root; 26 | nok $doc-uncached.root.doc === $doc-uncached.root.doc; 27 | nok @nodes1.head === @nodes2.head; 28 | nok @nodes1.tail === @nodes2.tail; 29 | nok @nodes1.head.getAttributeNode('att') === @nodes2.head.getAttributeNode('att'); 30 | } 31 | 32 | subtest 'with caching', { 33 | ok $doc-cached.config.with-cache; 34 | ok $doc-cached.root === $doc-cached.root; 35 | ok $doc-cached.root.doc === $doc-cached.root.doc; 36 | my @nodes1 = $doc-cached.root.children; 37 | my @nodes2 = $doc-cached.root.children; 38 | ok @nodes1.head === @nodes2.head; 39 | ok @nodes1.tail === @nodes2.tail; 40 | ok @nodes1.head.getAttributeNode('att') === @nodes2.head.getAttributeNode('att'); 41 | } 42 | 43 | subtest 'equivalence', { 44 | my @nodes1 = $doc-cached.root.children; 45 | my @nodes2 = $doc-uncached.root.children; 46 | ok @nodes1.head eqv @nodes2.head; 47 | ok @nodes1.tail eqv @nodes2.tail; 48 | } 49 | -------------------------------------------------------------------------------- /t/00xpath-object.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::Config; 5 | use LibXML::Document; 6 | use LibXML::Raw; 7 | use LibXML::Node::Set; 8 | use LibXML::Enums; 9 | 10 | plan 25; 11 | 12 | my xmlXPathObject $xo .= COERCE(42); 13 | is $xo.type, +XPATH_NUMBER; 14 | is-approx $xo.float, 42; 15 | is-approx $xo.select, 42; 16 | 17 | $xo .= COERCE(42.1); 18 | is $xo.type, +XPATH_NUMBER; 19 | is-approx $xo.float, 42.1; 20 | is-approx $xo.select, 42.1; 21 | 22 | $xo .= COERCE(Inf); 23 | is $xo.type, +XPATH_NUMBER; 24 | is xmlXPathObject::IsInf($xo.float), 1; 25 | is-deeply $xo.select, Inf; 26 | 27 | $xo .= COERCE(-Inf); 28 | is $xo.type, +XPATH_NUMBER; 29 | my int32 $is-inf = xmlXPathObject::IsInf($xo.float); 30 | is $is-inf, -1; 31 | is-deeply $xo.select, -Inf; 32 | 33 | $xo .= COERCE(NaN); 34 | is $xo.type, +XPATH_NUMBER; 35 | ok xmlXPathObject::IsNaN($xo.float); 36 | is-deeply $xo.select, NaN; 37 | 38 | $xo .= COERCE(True); 39 | is $xo.type, +XPATH_BOOLEAN; 40 | is-deeply $xo.select, True; 41 | 42 | $xo .= COERCE('Zsófia'); 43 | is $xo.type, +XPATH_STRING; 44 | is $xo.select, 'Zsófia'; 45 | 46 | my LibXML::Document $doc .= parse: :string(""); 47 | my LibXML::Node::Set:D $nodes = $doc.find('*/*'); 48 | is $nodes.size, 3; 49 | 50 | $xo .= COERCE($nodes.raw); 51 | is $xo.type, +XPATH_NODESET; 52 | is-deeply $xo.select, $nodes.raw; 53 | 54 | $xo .= COERCE($nodes[1].raw); 55 | is $xo.type, +XPATH_POINT; 56 | my $raw = $xo.select; 57 | isa-ok $raw, anyNode; 58 | # expect a one-element set, that contains the node 59 | my LibXML::Node $node .= box($raw); 60 | is $node.Str, ''; 61 | 62 | done-testing(); 63 | 64 | -------------------------------------------------------------------------------- /t/01basic.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::Config; 5 | use LibXML::Document; 6 | 7 | constant config = LibXML::Config; 8 | constant Min-LibXML-Version = v2.08.00; 9 | 10 | plan 8; 11 | 12 | my LibXML:D $p .= new(); 13 | 14 | my $version = $p.version; 15 | 16 | ok $version, 'LibXML.version is trueish'; 17 | sub yn($_) { .so ?? 'yes' !! 'no' } 18 | diag "Running libxml2 version: $version (module {LibXML.^ver}, Raku {$*RAKU.compiler.version})"; 19 | diag "libxml2 configuration: threads={yn config.have-threads} reader={yn config.have-reader} schemas={yn config.have-schemas} compression={yn config.have-compression} iconv={yn config.have-iconv}"; # 20 | given LibXML.config-version { 21 | diag "***NOTE was configured against libxml2 version $_ ***" 22 | unless $_ == $version 23 | } 24 | 25 | ok $version >= Min-LibXML-Version, "LibXML version is suppported" 26 | or diag "sorry this version of libxml is not supported ($version < {Min-LibXML-Version})"; 27 | 28 | for True, False -> $kb { 29 | lives-ok { config.keep-blanks = $kb }, 'set keep-blanks default'; 30 | is-deeply config.keep-blanks, $kb, 'get keep-blanks default'; 31 | } 32 | 33 | my Str $string = '

    Test

    '; 34 | my LibXML::Document:D $doc = $p.parse: :$string; 35 | 36 | $doc.config.skip-xml-declaration = True; 37 | 38 | is $doc.Str.chomp, $string, '$doc.Str'; 39 | is-deeply $doc.Str(:format).lines, ( 40 | '', 41 | ' ', 42 | '

    Test

    ', 43 | ' ', 44 | '' 45 | ), '$doc.Str(:format)'; 46 | -------------------------------------------------------------------------------- /t/13dtd.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::Dtd; 5 | 6 | plan 8; 7 | 8 | pass("Loaded"); 9 | 10 | my $dtdstr = 'samples/test.dtd'.IO.slurp; 11 | $dtdstr ~~ s/\n*$//; 12 | 13 | ok($dtdstr, "DTD String read"); 14 | 15 | subtest 'parse a DTD from a SYSTEM ID', { 16 | my LibXML::Dtd:D $dtd .= new('ignore', 'samples/test.dtd'); 17 | my @dtd-lines-in = $dtdstr.lines; 18 | my @dtd-lines-out = $dtd.Str.lines; 19 | @dtd-lines-out.shift; 20 | @dtd-lines-out.pop; 21 | is-deeply @dtd-lines-out, @dtd-lines-in, 'DTD String same as new string.' ; 22 | } 23 | 24 | subtest 'parse a DTD from a string', { 25 | 26 | my LibXML::Dtd $dtd .= parse: :string($dtdstr); 27 | ok $dtd, '.parse: :$string'; 28 | } 29 | 30 | subtest 'validate with the DTD', { 31 | my LibXML::Dtd $dtd .= parse: :string($dtdstr); 32 | ok $dtd, '.parse_string 2'; 33 | my $xml = LibXML.parse: :file('samples/article.xml'); 34 | ok $xml, 'parse the article.xml file'; 35 | ok $xml.is-valid($dtd), 'valid XML file'; 36 | ok $xml ~~ $dtd, 'ACCEPTS() on valid document'; 37 | lives-ok { $xml.validate($dtd) }; 38 | } 39 | 40 | subtest 'validate a bad document', { 41 | my LibXML::Dtd $dtd .= parse: :string($dtdstr); 42 | ok $dtd, '.parse_string 3'; 43 | my $xml = LibXML.parse: :file('samples/article_bad.xml'); 44 | nok $xml.is-valid($dtd), 'invalid XML'; 45 | nok $xml ~~ $dtd, 'ACCEPTS() on invalid document'; 46 | dies-ok { 47 | $xml.validate($dtd); 48 | }, '.validate throws an exception'; 49 | 50 | my LibXML $parser .= new(); 51 | ok($parser.validation = True, '.validation returns True'); 52 | # this one is OK as it's well formed (no DTD) 53 | 54 | dies-ok { 55 | $parser.parse: :file('samples/article_bad.xml'); 56 | }, 'Threw an exception'; 57 | dies-ok { 58 | $parser.parse: :file('samples/article_internal_bad.xml'); 59 | }, 'Throw an exception 2'; 60 | } 61 | 62 | # this test failed under Perl XML-LibXML-1.00 with a segfault because the 63 | # underlying DTD element in the C libxml library was freed twice 64 | 65 | subtest 'childNodes sanity', { 66 | my LibXML $parser .= new(); 67 | my $doc = $parser.parse: :file('samples/dtd.xml'); 68 | my @a = $doc.childNodes; 69 | is(+@a, 2, "Two child nodes"); 70 | } 71 | 72 | subtest 'Perl ticket #2021', { 73 | dies-ok { LibXML::Dtd.new("",""); }; 74 | lives-ok { 75 | my LibXML::Dtd:D $dtd .= new('', 'samples/test.dtd'); 76 | }, "LibXML::Dtd.new working correctly"; 77 | } 78 | -------------------------------------------------------------------------------- /t/16docnodes.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | plan 10; 4 | 5 | use LibXML; 6 | use LibXML::Element; 7 | use LibXML::Document; 8 | 9 | # this test fails under XML-LibXML-1.00 with a segfault after the 10 | # second parsing. it was fixed by putting in code in getChildNodes 11 | # to handle the special case where the node was the document node 12 | 13 | my $input = q:to; 14 | 15 | 16 | A B 17 | 18 | A 19 | 20 | B 21 | A B 22 | C 23 | 24 | 25 | EOD 26 | 27 | for 1 .. 3 -> $time { 28 | my LibXML $parser .= new(); 29 | my LibXML::Document:D $doc = $parser.parse: :string($input); 30 | my @a = $doc.getChildnodes; 31 | is +@a, 1, "1 Child node - time $time"; 32 | } 33 | 34 | my LibXML $parser .= new(); 35 | my $doc = $parser.parse: :string($input); 36 | for 1 .. 3 -> $time { 37 | lives-ok {my LibXML::Element:D $ = $doc.getFirstChild}, 38 | "first child is an Element - time No. $time"; 39 | } 40 | 41 | for 1 .. 3 -> $time { 42 | lives-ok {my LibXML::Element:D $ = $doc.getLastChild}, 43 | "last child is an element - time No. $time"; 44 | } 45 | 46 | { 47 | my LibXML::Document $doc .= new(); 48 | 49 | my LibXML::Element $node = $doc.create(LibXML::Element, 'test'); 50 | $node.setAttribute(contents => "\c[0xE4]"); 51 | $doc.setDocumentElement($node); 52 | $doc.encoding = 'utf-8'; 53 | is $node.Str(), qq{}, 'UTF-8 node serialize'; 54 | } 55 | -------------------------------------------------------------------------------- /t/18docfree.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | 4 | use LibXML; 5 | 6 | plan 1; 7 | for ^1000 { 8 | my LibXML::Document $doc .= new(); 9 | $doc.documentElement = $doc.createElement("node" ~ $_); 10 | $doc .= new; 11 | } 12 | pass 'doc new/free sanity'; 13 | 14 | -------------------------------------------------------------------------------- /t/20extras.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | 4 | plan 4; 5 | 6 | use LibXML; 7 | use LibXML::Attr; 8 | use LibXML::Document; 9 | 10 | my $string = "\n"; 11 | 12 | my LibXML $parser .= new(); 13 | 14 | subtest ':skip-xml-declaration, :tag-expansion', { 15 | my LibXML::Document:D $doc = $parser.parse: :$string; 16 | temp $doc.config.skip-xml-declaration = 1; 17 | is $doc.Str(), $string, ':skip-xml-declaration'; 18 | temp $doc.config.tag-expansion = True; 19 | is $doc.Str(), "\n", ':tag-expansion'; 20 | } 21 | 22 | subtest ':exand-entities', { 23 | temp $parser.config.skip-dtd = True; 24 | temp $parser.expand-entities = False; 25 | my LibXML::Document:D $doc = $parser.parse: :file( "samples/dtd.xml" ); 26 | my $test = "This is a valid document &foo; !\n"; 27 | is $doc.Str(:skip-xml-declaration), $test, ':!expand-entities'; 28 | } 29 | 30 | subtest 'cloneNode', { 31 | my LibXML::Document:D $doc = $parser.parse: :$string; 32 | my LibXML::Document:D $dclone = $doc.cloneNode(:deep); 33 | ok ! $dclone.isSameNode($doc), '.isSameNode() on cloned node'; 34 | ok $dclone.getDocumentElement(); 35 | ok $doc.Str() eq $dclone.Str(); 36 | 37 | my $clone = $doc.cloneNode(:!deep); # shallow 38 | ok ! $clone.isSameNode($doc); 39 | ok ! $clone.getDocumentElement().defined; 40 | $doc.getDocumentElement().unbindNode(); 41 | # allow 42 | is $doc.Str, $clone.Str, "unbind of document element"; 43 | } 44 | 45 | skip "attribute child nodes is deprecated"; 46 | #`( # depreacted 47 | subtest 'attribute child nodes' => { 48 | plan 3; 49 | my LibXML::Document:D $doc .= parse: :file; 50 | my $elem = $doc.createElement: "Test"; 51 | my LibXML::Attr:D $att = $doc.create: LibXML::Attr, :name, :value('xxx'); 52 | $att.addChild: $doc.createEntityReference('foo'); 53 | is $att.Str, "xxx test "; 54 | isa-ok $att.childNodes[1], 'LibXML::EntityRef'; 55 | $elem.setAttributeNode($att); 56 | is $elem.Str, ''; 57 | } 58 | ) 59 | -------------------------------------------------------------------------------- /t/21catalog.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | plan 1; 4 | 5 | use LibXML; 6 | use LibXML::Document; 7 | 8 | # the following document should not be able to get parsed 9 | # if the catalog is not available 10 | 11 | lives-ok { 12 | my LibXML::Document:D $doc = LibXML.new( catalog => "samples/catalog.xml" ).parse: :string(q:to); 13 | 16 |
    17 | Something here 18 | 12345 19 | 2001-04-01 20 | XML.com 21 |
    Foo
    22 | Here's some leading text 23 | And here is the rest... 24 |
    25 | EOF 26 | }, 'Doc was parsed with catalog'; 27 | -------------------------------------------------------------------------------- /t/23rawfunctions.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | plan 1; 4 | use LibXML; 5 | 6 | my $doc = LibXML.createDocument; 7 | 8 | my $t1 = $doc.createTextNode( "foo" ); 9 | my $t2 = $doc.createTextNode( "bar" ); 10 | 11 | $t1.addChild( $t2 ); 12 | 13 | lives-ok { 14 | my Str:D $v = $t2.nodeValue; 15 | }; 16 | -------------------------------------------------------------------------------- /t/30keep_blanks.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | # ensure keep-blanks plays with .parse-balanced() 3 | 4 | use Test; 5 | use LibXML; 6 | 7 | plan 2; 8 | 9 | my $xml = q:to; 10 | 11 | EOF 12 | 13 | my LibXML $p .= new; 14 | $p.keep-blanks = True; 15 | 16 | is( 17 | $p.parse-balanced( :string($xml)).serialize(), 18 | " \n", 19 | 'keep-blanks keeps the blanks after a roundtrip.', 20 | ); 21 | 22 | $p.keep-blanks = False; 23 | 24 | is( 25 | $p.parse-balanced( :string($xml)).serialize(), 26 | "\n", 27 | '!keep-blanks removes the blanks after a roundtrip.', 28 | ); 29 | -------------------------------------------------------------------------------- /t/35huge_mode.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | # Having 'XML_PARSE_HUGE' enabled can make an application vulnerable to 3 | # denial of service through entity expansion attacks. This test script 4 | # confirms that huge document mode is disabled by default and that this 5 | # does not adversely affect expansion of sensible entity definitions. 6 | # 7 | 8 | use Test; 9 | use LibXML; 10 | use LibXML::Document; 11 | 12 | plan 4; 13 | 14 | my $benign_xml = q:to; 15 | 16 | 18 | ]> 19 | &lol; 20 | EOF 21 | 22 | my $evil_xml = q:to; 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | ]> 44 | &lolH; 45 | EOF 46 | 47 | my LibXML $parser .= new; 48 | #$parser->set_option(huge => 0); 49 | ok !$parser.get-option('huge'), "huge mode disabled by default"; 50 | 51 | throws-like { my $xml = $parser.parse: :string($evil_xml), :expand-entities; note $xml.Str.chars }, X::LibXML::Parser, :message(/entity/), "exception thrown during parse"; 52 | 53 | $parser .= new; 54 | 55 | my LibXML::Document $doc; 56 | lives-ok { $doc = $parser.parse: :string($benign_xml); }, "no exception thrown during parse"; 57 | 58 | my $body = $doc.findvalue( '/lolz' ); 59 | is $body, 'haha', 'entity was parsed and expanded correctly'; 60 | 61 | exit; 62 | 63 | -------------------------------------------------------------------------------- /t/41xinclude.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use LibXML; 3 | use Test; 4 | plan 7; 5 | 6 | my LibXML $parser .= new; 7 | my $file = 'test/xinclude/test.xml'; 8 | { 9 | $parser.expand-xinclude = False; 10 | $parser.expand-entities = True; 11 | unlike $parser.parse(:$file).Str, /'IT WORKS'/, 'parse: :!expand-xinclude, :expand-entities';; 12 | } 13 | { 14 | $parser.expand-xinclude = True; 15 | $parser.expand-entities = False; 16 | unlike $parser.parse(:$file).Str, /'IT WORKS'/, 'parse: :expand-xinclude, :!expand-entities';; 17 | } 18 | { 19 | $parser.expand-xinclude = True; 20 | $parser.expand-entities = True; 21 | like $parser.parse(:$file).Str, /'IT WORKS'/, 'parse: :expand-xinclude, :expand-entities';; 22 | } 23 | { 24 | $parser.expand-xinclude = False; 25 | my $doc = $parser.parse: :$file; 26 | ok $doc.process-xincludes(:!expand-entities), 'process-xincludes: :!expand-xinclude, :!expand-entities'; 27 | unlike $doc.Str, /'IT WORKS'/, 'process-xincludes: :!expand-xinclude, :!expand-entities'; 28 | } 29 | { 30 | my $doc = $parser.parse :$file; 31 | ok $doc.process-xincludes(:expand-entities), 'process-xincludes: :!expand-xinclude, :expand-entities'; 32 | like $doc.Str, /'IT WORKS'/, 'process-xincludes: :!expand-xinclude, :expand-entities'; 33 | } 34 | -------------------------------------------------------------------------------- /t/42common.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML::Enums; 4 | 5 | plan 2; 6 | 7 | pass('Loading'); 8 | 9 | ######################### 10 | 11 | is(+XML_ELEMENT_NODE, 1, 'XML_ELEMENT_NODE is 1.' ); 12 | 13 | -------------------------------------------------------------------------------- /t/44extent.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::Config; 5 | use LibXML::Enums; 6 | 7 | constant config = LibXML::Config; 8 | 9 | plan 7; 10 | 11 | config.external-entity-loader = &handler; 12 | 13 | my LibXML $parser .= new: :expand-entities; 14 | 15 | $parser.config.parser-locking = True; 16 | 17 | sub handler(*@p) { 18 | return @p.map({$_//''}).join: ','; 19 | } 20 | 21 | my $xml = q:to; 22 | 23 | 25 | 26 | ]> 27 | 28 | &a; 29 | &b; 30 | 31 | EOF 32 | my $xml_out = $xml; 33 | $xml_out .= subst('&a;', 'file:/dev/null,//foo/bar/b', :g); 34 | $xml_out .= subst('&b;', 'file:///dev/null,', :g); 35 | 36 | my $doc = $parser.parse: :string($xml); 37 | 38 | is $doc.Str(), $xml_out; 39 | 40 | my $xml_out2 = $xml; $xml_out2 .= subst(/'&'[a|b]';'/, '', :g); 41 | 42 | $parser.config.external-entity-loader = -> *@ { '' }; 43 | $doc = $parser.parse: :string($xml); 44 | is $doc.Str(), $xml_out2; 45 | 46 | config.external-entity-loader = -> *@ { '' } 47 | 48 | $parser.set-options( 49 | expand_entities => 0, 50 | recover => 2, 51 | ); 52 | $doc = $parser.parse: :string($xml); 53 | is $doc.Str(), $xml; 54 | 55 | for $doc.findnodes('/root/*') -> $el { 56 | ok $el.hasChildNodes; 57 | is $el.firstChild.nodeType, +XML_ENTITY_REF_NODE; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /t/45regex.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML::RegExp; 4 | use LibXML::Parser::Context; 5 | 6 | plan 22; 7 | 8 | { 9 | my $regexp = '[0-9]{5}(-[0-9]{4})?'; 10 | my LibXML::RegExp $re .= new: :$regexp; 11 | 12 | ok $re, 'Regex object was initted.'; 13 | ok ! $re.matches('00'), 'Does not match 00'; 14 | ok ! $re.matches('00-'), 'Does not match 00-'; 15 | ok $re.matches('12345'), 'Matches 12345'; 16 | ok !$re.matches('123456'), 'Does not match 123456'; 17 | 18 | ok $re.matches('12345-1234'), 'Matches 12345-1234'; 19 | ok ! $re.matches(' 12345-1234'), 'Does not match leading space'; 20 | ok ! $re.matches(' 12345-12345'), 'Leading space No. 2'; 21 | ok ! $re.matches('12345-1234 '), 'Trailing space'; 22 | 23 | ok '12345-1234' ~~ $re, 'ACCEPTS match'; 24 | nok '12345-1234' !~~ $re, 'ACCEPTS match negated'; 25 | ok ' 12345-1234' !~~ $re, 'ACCEPTS non-match negated'; 26 | nok ' 12345-1234' ~~ $re, 'ACCEPTS non-match'; 27 | ok $re ~~ LibXML::RegExp, 'ACCEPTS obj/class match'; 28 | nok $re ~~ LibXML::ErrorHandling, 'ACCEPTS obj/class non-match'; 29 | nok Str ~~ $re, 'ACCEPTS class/obj non-match'; 30 | nok Str ~~ LibXML::RegExp, 'ACCEPTS class/class non-match'; 31 | ok LibXML::RegExp ~~ LibXML::RegExp, 'ACCEPTS class/class match'; 32 | 33 | ok $re.isDeterministic, 'Regex is deterministic'; 34 | } 35 | 36 | { 37 | my $nondet_regex = '(bc)|(bd)'; 38 | my LibXML::RegExp $nondet_re .= new(regexp => $nondet_regex); 39 | 40 | ok $nondet_re, 'Non deterministic re was initted'; 41 | ok ! $nondet_re.isDeterministic, 'It is not deterministic'; 42 | } 43 | 44 | # silence this test 45 | my $errors; 46 | LibXML::Parser::Context.SetGenericErrorFunc(-> $fmt, |c { $errors++ }) 47 | unless LibXML::Config.version >= v2.13.00; 48 | 49 | { 50 | my $bad_regex = '[0-9]{5}(-[0-9]{4}?'; 51 | dies-ok { LibXML::RegExp.new(regexp => $bad_regex); }, 'An exception was thrown on bad regex'; 52 | } 53 | -------------------------------------------------------------------------------- /t/46err_column.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | # ensure .column() and other error fields are correct 3 | use Test; 4 | use LibXML; 5 | use LibXML::DocumentFragment; 6 | use LibXML::Enums; 7 | use LibXML::ErrorHandling; 8 | 9 | plan 2; 10 | 11 | throws-like 12 | { 13 | LibXML.parse: :string( 14 | '' 18 | # Error here ---^ 19 | ), 20 | :URI, 21 | }, 22 | X::LibXML::Parser, 23 | "XML_ERR_DOCUMENT_END", 24 | :file, 25 | :line(1), 26 | :level(XML_ERR_FATAL), 27 | :code(XML_ERR_DOCUMENT_END | XML_ERR_GT_REQUIRED), 28 | :domain-num(XML_FROM_PARSER), 29 | :domain, 30 | :column{ LibXML.version < v2.09.02 || 203 }, # The older versions are unreliable, make it just True 31 | :msg(*.contains('Extra content at the end of the document'|"Couldn't find end of Start Tag foo")), 32 | :message(rx:s/ 33 | 'test.xml:1: parser error : attributes construct error'/), 34 | :prev{ 35 | ?( $^prev ~~ X::LibXML::Parser 36 | && $prev.domain-num == XML_FROM_PARSER 37 | && (($prev.prev // $prev).msg.chomp eq 'attributes construct error' ) 38 | ) 39 | }, 40 | ; 41 | 42 | throws-like 43 | { 44 | LibXML::DocumentFragment.parse: :string('XX'), :balanced; 45 | }, 46 | X::LibXML::Parser, 47 | "XML_ERR_NOT_WELL_BALANCED", 48 | :file(Str:U), 49 | :line(1), 50 | :level(XML_ERR_FATAL), 51 | :code(XML_ERR_NOT_WELL_BALANCED | XML_ERR_TAG_NAME_MISMATCH), 52 | :column{ LibXML.version < v2.09.02 || 13 }, 53 | :domain-num(XML_FROM_PARSER), 54 | :domain, 55 | :message(rx:s/':1: parser error : Opening and ending tag mismatch: foo line 1 and bar'/), 56 | ; 57 | -------------------------------------------------------------------------------- /t/47load_xml_callbacks.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # ensure operation of input callbacks with .load() 4 | use Test; 5 | plan 3; 6 | 7 | use LibXML; 8 | use LibXML::InputCallback; 9 | use LibXML::Config; 10 | 11 | LibXML::Config.parser-locking = True; 12 | 13 | { 14 | my Bool $got-open; 15 | my Bool $got-read; 16 | my Bool $got-close; 17 | 18 | my LibXML::InputCallback $input-callbacks .= new(); 19 | $input-callbacks.register-callbacks( 20 | -> $ { 1 }, 21 | -> $file { $got-open++; $file.IO.open(:r) }, 22 | -> $fh, $n { $got-read++; $fh.read($n); }, 23 | -> $fh { $got-close++; $fh.close }, 24 | ); 25 | 26 | my LibXML $xml-parser .= new(); 27 | $xml-parser.input-callbacks($input-callbacks); 28 | 29 | my $location = 'samples/dromeds.xml'; 30 | 31 | $xml-parser.load: :$location; 32 | 33 | ok $got-open, 'load_xml() encountered the open InputCallback'; 34 | 35 | ok $got-read, 'load_xml() encountered the read InputCallback'; 36 | 37 | ok $got-close, 'load_xml() encountered the close InputCallback'; 38 | } 39 | -------------------------------------------------------------------------------- /t/48importing_nodes_IDs.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | =begin pod 3 | 4 | =head1 DESCRIPTION 5 | 6 | Ensure IDs of elements are not lost when importing nodes from another document. 7 | =end pod 8 | 9 | use Test; 10 | plan 4; 11 | 12 | use LibXML; 13 | use LibXML::Document; 14 | use LibXML::Element; 15 | 16 | { 17 | my LibXML::Document:D $doc = LibXML.load(string => q:to); 18 | 19 | item1 20 | 21 | EOT 22 | 23 | my LibXML::Element $elem = $doc.getElementById('id1'); 24 | ok $elem.defined, 'Orig doc has id1'; 25 | 26 | is $elem.textContent(), 'item1', 'Content of orig doc elem id1'; 27 | 28 | my LibXML::Document:D $doc2 = LibXML.createDocument( "1.0", "UTF-8" ); 29 | $doc2.setDocumentElement( $doc2.importNode( $doc.documentElement() ) ); 30 | 31 | my LibXML::Element $elem2 = $doc2.getElementById('id1'); 32 | ok defined($elem2), 'Doc2 after importNode has id1'; 33 | 34 | is $elem2.textContent(), 'item1', 'Doc2 after importNode has id1'; 35 | } 36 | 37 | =begin pod 38 | 39 | =head1 COPYRIGHT & LICENSE 40 | 41 | Copyright 2011 by Shlomi Fish 42 | 43 | This program is distributed under the MIT (X11) License: 44 | L 45 | 46 | Permission is hereby granted, free of charge, to any person 47 | obtaining a copy of this software and associated documentation 48 | files (the "Software"), to deal in the Software without 49 | restriction, including without limitation the rights to use, 50 | copy, modify, merge, publish, distribute, sublicense, and/or sell 51 | copies of the Software, and to permit persons to whom the 52 | Software is furnished to do so, subject to the following 53 | conditions: 54 | 55 | The above copyright notice and this permission notice shall be 56 | included in all copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 59 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 60 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 61 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 62 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 63 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 64 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 65 | OTHER DEALINGS IN THE SOFTWARE. 66 | 67 | =end pod 68 | -------------------------------------------------------------------------------- /t/49global_extent.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::Config; 5 | constant config = LibXML::Config; 6 | 7 | plan 1; 8 | 9 | sub handler(*@p) { 10 | "ENTITY:" ~ @p.map({$_//''}).join: ','; 11 | } 12 | 13 | # global entity loader 14 | config.external-entity-loader = &handler; 15 | 16 | my LibXML $parser .= new: :expand-entities; 17 | 18 | $parser.config.parser-locking = True; 19 | 20 | my $xml = q:to; 21 | 22 | 24 | 25 | ]> 26 | 27 | &a; 28 | &b; 29 | 30 | EOF 31 | 32 | my $xml_out = $xml; 33 | $xml_out ~~ s|'&a;'|ENTITY:file:/dev/null,//foo/bar/b|; 34 | $xml_out ~~ s|'&b;'|ENTITY:file:///dev/null,|; 35 | 36 | my $doc = $parser.parse: :string($xml); 37 | 38 | is $doc.Str, $xml_out; 39 | -------------------------------------------------------------------------------- /t/60error_prev_chain.t: -------------------------------------------------------------------------------- 1 | # This test script checks an error chain cannot be too long, because if it is 2 | # it consumes a lot of RAM. 3 | 4 | use v6; 5 | use Test; 6 | use LibXML; 7 | use LibXML::Config; 8 | use LibXML::Enums; 9 | 10 | LibXML::Config.max-errors = 80; 11 | 12 | { 13 | my LibXML $parser .= new(); 14 | $parser.validation(0); 15 | $parser.load_ext_dtd(0); 16 | 17 | try { 18 | $parser.parse: :file('samples/JBR-ALLENtrees.htm'); 19 | }; 20 | 21 | my $err = $!; 22 | isa-ok $err, 'X::LibXML::TooManyErrors'; 23 | isa-ok $err.prev, 'X::LibXML::Parser'; 24 | is-deeply $err.level, XML_ERR_FATAL; 25 | my $count = 0; 26 | 27 | while defined($err) && $count < 200 { 28 | $count++; 29 | $err = $err.prev(); 30 | } 31 | 32 | nok defined($err), "Reached the end of the chain."; 33 | } 34 | done-testing; 35 | 36 | =begin pod 37 | =head1 COPYRIGHT & LICENSE 38 | 39 | Copyright 2011 by Shlomi Fish 40 | 41 | This program is distributed under the MIT (X11) License: 42 | L 43 | 44 | Permission is hereby granted, free of charge, to any person 45 | obtaining a copy of this software and associated documentation 46 | files (the "Software"), to deal in the Software without 47 | restriction, including without limitation the rights to use, 48 | copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the 50 | Software is furnished to do so, subject to the following 51 | conditions: 52 | 53 | The above copyright notice and this permission notice shall be 54 | included in all copies or substantial portions of the Software. 55 | 56 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 57 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 58 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 59 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 60 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 61 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 62 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 63 | OTHER DEALINGS IN THE SOFTWARE. 64 | 65 | =cut 66 | =end pod 67 | -------------------------------------------------------------------------------- /t/61error.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use Test; 3 | use LibXML; 4 | use LibXML::ErrorHandling; 5 | 6 | plan 3; 7 | 8 | my LibXML $p .= new; 9 | 10 | my $xmlstr = "\n"; 11 | 12 | try { 13 | my $doc = $p.parse: :string( $xmlstr ); 14 | }; 15 | 16 | my $err = $!; 17 | isa-ok($err, X::LibXML::Parser, 'Exception is of type parser error.'); 18 | is($err.domain(), 'parser', 'Error is in the parser domain'); 19 | is($err.line(), 1, 'Error is on line 1.'); 20 | -------------------------------------------------------------------------------- /t/META6.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "LibXML test suite modules", 3 | "license": "Artistic-2.0", 4 | "name": "LibXML::t", 5 | "perl": "6.c", 6 | "provides": { 7 | "Collector": "lib/Collector.rakumod", 8 | "Counter": "lib/Counter.rakumod", 9 | "Stacker": "lib/Stacker.rakumod" 10 | }, 11 | "source-url": "https://github.com/libxml-raku/LibXML-raku.git", 12 | "version": "0.0.1" 13 | } 14 | -------------------------------------------------------------------------------- /t/data/chinese.xml: -------------------------------------------------------------------------------- 1 | 2 | 主題 3 | 關鍵詞 4 | 5 | -------------------------------------------------------------------------------- /t/issue#025.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use LibXML; 3 | use LibXML::Document; 4 | use Test; 5 | plan 1; 6 | 7 | my $html = q:to/HTML/; 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | HTML 16 | 17 | my LibXML $parser .= new; 18 | my LibXML::Document:D $doc = $parser.parse( 19 | :string($html), 20 | :recover, 21 | :suppress-errors, 22 | :suppress-warnings, 23 | :html 24 | ); 25 | 26 | my @nodes = $doc.findnodes("//aside[@class='hello']"); 27 | ok @nodes > 0; 28 | -------------------------------------------------------------------------------- /t/issue#095.t: -------------------------------------------------------------------------------- 1 | use v6; 2 | use LibXML; 3 | use LibXML::Element; 4 | use Test; 5 | plan 1; 6 | 7 | my $html = q:to/XML/; 8 | 9 | 10 | Some text 11 | 12 | XML 13 | 14 | my LibXML $parser .= new; 15 | my $doc = $parser.parse( 16 | :string($html), 17 | :!blanks, 18 | ); 19 | 20 | throws-like { for $doc.root.childNodes -> LibXML::Element $re {} }, X::TypeCheck::Binding::Parameter; 21 | -------------------------------------------------------------------------------- /t/lib/Collector.rakumod: -------------------------------------------------------------------------------- 1 | use v6; 2 | unit class Collector; 3 | has &.cb; 4 | 5 | method _calc_op_callback {...} 6 | 7 | submethod TWEAK(:&gen-cb!) { 8 | &!cb = &gen-cb(self._calc_op_callback()); 9 | } 10 | 11 | -------------------------------------------------------------------------------- /t/lib/Counter.rakumod: -------------------------------------------------------------------------------- 1 | unit class Counter; 2 | use Collector; 3 | also is Collector; 4 | use Test; 5 | has UInt $!count; 6 | 7 | method _calc_op_callback { 8 | sub { ++$!count } 9 | } 10 | 11 | method test(UInt $value, $blurb) { 12 | my $rv := is $!count, $value, $blurb; 13 | $!count = 0; 14 | $rv; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /t/lib/Stacker.rakumod: -------------------------------------------------------------------------------- 1 | unit class Stacker; 2 | use Collector; 3 | also is Collector; 4 | 5 | use Test; 6 | 7 | has @.stack is rw; 8 | has &.gen-cb; 9 | 10 | method _calc_op_callback { 11 | -> $item { @!stack.push: $item } 12 | } 13 | 14 | method test(@value, $blurb) { 15 | my $rv := is-deeply @!stack, @value, $blurb; 16 | @!stack = []; 17 | $rv; 18 | } 19 | -------------------------------------------------------------------------------- /test/compression/test.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/test/compression/test.xml.gz -------------------------------------------------------------------------------- /test/dtd/namespaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | ]> 10 | 11 | abcd 12 | 13 | -------------------------------------------------------------------------------- /test/dtd/note-external-dtd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tove 5 | Jani 6 | Reminder 7 | Don't forget me this weekend! 8 | 9 | -------------------------------------------------------------------------------- /test/dtd/note-internal-dtd.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | ]> 10 | 11 | Tove 12 | Jani 13 | Reminder 14 | Don't forget me this weekend! 15 | 16 | -------------------------------------------------------------------------------- /test/dtd/note-no-dtd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Tove 4 | Jani 5 | Reminder 6 | Don't forget me this weekend! 7 | 8 | -------------------------------------------------------------------------------- /test/dtd/note.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/dtd/parameter-entities.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /test/dtd/parameter-entities.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | ]> 6 | 7 |

    Level 1 Header

    8 |

    This is a test of DtD parameter entities

    9 |

    Level 3 Header

    10 |
    11 | -------------------------------------------------------------------------------- /test/empty.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libxml-raku/LibXML-raku/73e4350ce2ac41024bcc80b16d6ccea9382e1a48/test/empty.txt -------------------------------------------------------------------------------- /test/relaxng/badschema.rng: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/relaxng/demo.rng: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/relaxng/demo.xml: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /test/relaxng/demo2.rng: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/relaxng/demo3.rng: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /test/relaxng/demo4.rng: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /test/relaxng/invaliddemo.xml: -------------------------------------------------------------------------------- 1 | hello 2 | -------------------------------------------------------------------------------- /test/relaxng/schema.rng: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/schema/badschema.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/schema/demo.xml: -------------------------------------------------------------------------------- 1 | 2 | foo 3 | 2 4 | 1.0 5 | No comment ! 6 | 7 | -------------------------------------------------------------------------------- /test/schema/invaliddemo.xml: -------------------------------------------------------------------------------- 1 | 2 | foo 3 | 2 4 | 1.0 5 | No comment ! 6 | 7 | -------------------------------------------------------------------------------- /test/schema/net.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/schema/schema.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/textReader/SR2006_countries_config.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 13 | 14 | 15 | 17 | 18 | 19 | 21 | -------------------------------------------------------------------------------- /test/textReader/countries.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/xinclude/entity.txt: -------------------------------------------------------------------------------- 1 | IT WORKS! 2 | -------------------------------------------------------------------------------- /test/xinclude/test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/xinclude/xinclude.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | ]> 5 | 6 | &trend; 7 | 8 | -------------------------------------------------------------------------------- /xt/release/version.t: -------------------------------------------------------------------------------- 1 | use LibXML; 2 | use Test; 3 | use JSON::Fast; 4 | 5 | plan 2; 6 | 7 | my %META6 = from-json "META6.json".IO.slurp; 8 | my Version:D() $ver = LibXML.^ver; 9 | 10 | subtest 'LibXML.^ver', { 11 | ok $ver, 'is Trueish'; 12 | my @parts = $ver.Str.split: '.'; 13 | 14 | is +@parts, 3, 'is semantic (X.Y.Z)'; 15 | is-deeply ~$ver, %META6, "consistant with META6" 16 | or diag "Mismatch between LibXML.^ver({LibXML.^ver.raku}) and META6({%META6.raku})" 17 | } 18 | 19 | subtest 'LibXML.^api', { 20 | my Version:D() $api = LibXML.^api; 21 | ok $api, 'is Trueish'; 22 | my @parts = $api.Str.split: '.'; 23 | 24 | ok 2 <= +@parts <= 3, 'is of form X.Y[.Z]'; 25 | my $ver-base = Version.new('v' ~ $ver.parts[0..*-2].join('.')~'.0'); 26 | ok $ver-base <= $api <= $ver, "api within range ($ver-base <= $api <= $ver)"; 27 | 28 | is-deeply ~$api, %META6, "consistant with META6" 29 | or diag "Mismatch between LibXML.^api({LibXML.^api.raku}) and META6({%META6.raku})"; 30 | } 31 | -------------------------------------------------------------------------------- /xt/xpath/01_simple_basic_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Document; 6 | 7 | plan 7; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Text 20 | 21 | 22 | 23 | 24 | ENDXML 25 | 26 | my $set; 27 | $set = $x.find("/"); 28 | isa-ok $set[0], LibXML::Document, 'found one node'; 29 | 30 | $set = $x.find("/AAA"); 31 | isa-ok $set[0], LibXML::Node, 'found one node'; 32 | is $set[0].name, 'AAA', 'node name is AAA'; 33 | 34 | $set = $x.find("/AAA/BBB"); 35 | is $set.elems, 3 , 'found three nodes'; 36 | is $set[0].name, 'BBB', 'node name is BBB'; 37 | 38 | $set = $x.find("/AAA/DDD/BBB"); 39 | is $set.elems, 2 , 'found 2 nodes'; 40 | is $set[0].name, 'BBB', 'node name is BBB'; 41 | 42 | done-testing; 43 | -------------------------------------------------------------------------------- /xt/xpath/02_descendant_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 4; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ENDXML 17 | 18 | my $set; 19 | $set = $x.find("//BBB"); 20 | is $set.elems, 5 , 'found one node'; 21 | is $set[0].name, 'BBB', 'node name is BBB'; 22 | 23 | $set = $x.find("//DDD/BBB"); 24 | is $set.elems, 3 , 'found three nodes'; 25 | is $set[0].name, 'BBB', 'node name is BBB'; 26 | 27 | done-testing; 28 | -------------------------------------------------------------------------------- /xt/xpath/03_start_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 6; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ENDXML 35 | 36 | my $set; 37 | $set = $x.find("/AAA/CCC/DDD/*"); 38 | is $set.elems, 4 , 'found one node'; 39 | is $set[0].name, 'BBB', 'node name is BBB'; 40 | 41 | $set = $x.find("/*/*/*/BBB"); 42 | is $set.elems, 5 , 'found 5 nodes'; 43 | is $set[0].name, 'BBB', 'node name is BBB'; 44 | for $set.values -> $node { 45 | say $node; 46 | } 47 | 48 | $set = $x.find("//*"); 49 | is $set.elems, 17 , 'found 17 nodes'; 50 | is $set[0].name, 'AAA', 'node name is BBB'; 51 | 52 | done-testing; 53 | -------------------------------------------------------------------------------- /xt/xpath/04_pos_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Node; 6 | 7 | plan 8; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | ENDXML 17 | 18 | my $set; 19 | $set = $x.find('/AAA/BBB[1]'); 20 | isa-ok $set[0], LibXML::Node, 'found one node'; 21 | is $set[0].name, 'BBB', 'node name is BBB'; 22 | is $set[0].attribs, 'first', 'right node is selected'; 23 | 24 | $set = $x.find('/AAA/BBB[1]/@id'); 25 | isa-ok $set[0], LibXML::Attr, 'found one node'; 26 | is $set, 'first', 'node attrib is first'; 27 | 28 | $set = $x.find('/AAA/BBB[ last() ]'); 29 | isa-ok $set[0], LibXML::Node, 'found one node'; 30 | is $set[0].name, 'BBB', 'node name is BBB'; 31 | is $set[0].attribs, 'last', 'right node is selected'; 32 | 33 | done-testing; 34 | -------------------------------------------------------------------------------- /xt/xpath/05_attributes_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Node; 6 | 7 | plan 10; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | ENDXML 17 | 18 | my $set; 19 | $set = $x.find('//BBB[ @id ]'); 20 | is $set.elems, 2 , 'found one node'; 21 | is $set[0].name, 'BBB', 'node name is BBB'; 22 | is $set[1].name, 'BBB', 'node name is BBB'; 23 | 24 | $set = $x.find('//BBB[ @name ]'); 25 | isa-ok $set[0], LibXML::Node, 'found one node'; 26 | is $set[0].name, 'BBB', 'node name is BBB'; 27 | 28 | $set = $x.find('//BBB[ @* ]'); 29 | is $set.elems, 3 , 'found 3 node'; 30 | is $set[0].name, 'BBB', 'node name is BBB'; 31 | 32 | $set = $x.find('//BBB[ not( @* ) ]'); 33 | say $set; 34 | isa-ok $set[0], LibXML::Node, 'found one node'; 35 | is $set[0].name, 'BBB', 'node name is BBB'; 36 | is $set[0].attribs.elems, 0, 'and node really has no attribute'; 37 | 38 | done-testing; 39 | -------------------------------------------------------------------------------- /xt/xpath/06_attributes_val_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Node; 6 | 7 | plan 6; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | ENDXML 16 | 17 | my $set; 18 | $set = $x.find('//BBB[ @id = "b1" ]'); 19 | isa-ok $set[0], LibXML::Node, 'found one node'; 20 | is $set[0].name, 'BBB', 'node name is BBB'; 21 | 22 | $set = $x.find('//BBB[ @name = "bbb" ]', :to-list(True)); 23 | is $set.elems, 1 , 'found one attrib'; 24 | is $set[0].name, 'BBB', 'node name is BBB'; 25 | 26 | $set = $x.find('//BBB[ normalize-space(@name) = "bbb" ]'); 27 | is $set.elems, 2 , 'found one node'; 28 | is $set[0].name, 'BBB', 'node name is BBB'; 29 | 30 | done-testing; 31 | -------------------------------------------------------------------------------- /xt/xpath/07_count_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 10; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | ENDXML 16 | 17 | my $set; 18 | $set = $x.find('count(/AAA/*)'); 19 | is $set, 4, 'found 3 nodes'; 20 | 21 | $set = $x.find('count(/AAA/*) = 4'); 22 | is $set, True, 'found 3 nodes'; 23 | 24 | $set = $x.find('count(/AAA/*) = 3'); 25 | is $set, False, 'found 3 nodes'; 26 | 27 | $set = $x.find('//*[ count(BBB) = 2 ]', :to-list(True)); 28 | is $set.elems, 1 , 'found one node'; 29 | is $set[0].name, 'DDD', 'node name is BBB'; 30 | 31 | $set = $x.find('//*[ count(*) = 2]'); 32 | is $set.elems, 2 , 'found two nodes'; 33 | is $set[0].name, 'DDD', 'node name is DDD'; 34 | is $set[1].name, 'EEE', 'node name is EEE'; 35 | 36 | $set = $x.find('//*[ count(*) = 3]', :to-list(True)); 37 | is $set.elems, 1 , 'found one node'; 38 | is $set[0].name, 'CCC', 'node name is CCC'; 39 | 40 | done-testing; 41 | -------------------------------------------------------------------------------- /xt/xpath/08_name_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 6; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | ENDXML 15 | 16 | my $set; 17 | 18 | $set = $x.find('//*[ name() = "BBB" ]'); 19 | is $set.elems, 5 , 'found one node'; 20 | is $set[0].name, 'BBB', 'node name is BBB'; 21 | 22 | $set = $x.find('//*[ starts-with(name(), "B") ]'); 23 | is $set.elems, 7 , 'found two nodes'; 24 | is $set[0].name, 'BCC', 'node name is BCC'; 25 | 26 | $set = $x.find('//*[ contains(name(), "C") ]'); 27 | is $set.elems, 3 , 'found one node'; 28 | is $set[0].name, 'BCC', 'node name is BCC'; 29 | 30 | done-testing; 31 | -------------------------------------------------------------------------------- /xt/xpath/09_string_length_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 10; 7 | 8 | my $x; 9 | my $set; 10 | 11 | $x = LibXML.parse(string => q:to/ENDXML/); 12 | para one 13 | ENDXML 14 | 15 | $set = $x.find('/doc/text()'); 16 | nok $set, 'nothing found'; 17 | #isa-ok $set, XML::XPath::Result ,'nothing found'; 18 | 19 | $set = $x.find('string-length( /doc/text() )'); 20 | nok $set, 'nothing found'; 21 | 22 | $x = LibXML.parse(string => q:to/ENDXML/); 23 | 24 | para one has bold text 25 | 26 | ENDXML 27 | 28 | $set = $x.find('/doc/text()'); 29 | is $set.elems, 2, 'found 2 text nodes'; 30 | 31 | is $set[0].text, "\n ", 'first text is correct'; 32 | is $set[1].text, "\n", 'first text is correct'; 33 | 34 | $set = $x.find('string-length( /doc/text() )'); 35 | is $set, 3, 'XML trimmed string length is 3'; 36 | 37 | $set = $x.find('/doc/para/text()'); 38 | is $set.elems, 2, 'found 2 text nodes'; 39 | is $set[0].text, "para one has ", 'first text is correct'; 40 | is $set[1].text, " text", 'first text is correct'; 41 | 42 | $set = $x.find('string-length( /doc/para/text() )'); 43 | is $set, 13, 'XML trimmed string length is 1'; 44 | 45 | done-testing; 46 | -------------------------------------------------------------------------------- /xt/xpath/09_string_length_predicate_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 3; 7 | 8 | my $set; 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ENDXML 21 | 22 | $set = $x.find('//*[ string-length(name()) = 3 ]'); 23 | is $set.elems, 2, 'found 2 text nodes'; 24 | 25 | $set = $x.find('//*[ string-length(name()) < 3 ]'); 26 | is $set.elems, 4, 'found 2 text nodes'; 27 | 28 | $set = $x.find('//*[ string-length(name()) > 3 ]'); 29 | is $set.elems, 3, 'found 2 text nodes';# 30 | 31 | done-testing; 32 | -------------------------------------------------------------------------------- /xt/xpath/10_pipe_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 3; 7 | 8 | my $set; 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | ENDXML 17 | 18 | $set = $x.find('//CCC | //BBB'); 19 | is $set.elems, 3, 'found 3 nodes'; 20 | 21 | $set = $x.find('/AAA/EEE | //BBB'); 22 | is $set.elems, 2, 'found 2 nodes'; 23 | 24 | $set = $x.find('/AAA/EEE | //DDD/CCC | /AAA | //BBB'); 25 | is $set.elems, 4, 'found 4 nodes'; 26 | 27 | done-testing; 28 | -------------------------------------------------------------------------------- /xt/xpath/11_axis_child_find.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | ENDXML 16 | 17 | my $one-set; 18 | my $other-set; 19 | $one-set = $x.find('/child::AAA'); 20 | $other-set = $x.find('/AAA'); 21 | 22 | ok($one-set.is-equiv($other-set), 'explicit axis child test'); 23 | 24 | $one-set = $x.find('/child::AAA/child::BBB'); 25 | $other-set = $x.find('/AAA/BBB'); 26 | 27 | ok($one-set.is-equiv($other-set), 'explicit axis child test'); 28 | 29 | done-testing; 30 | -------------------------------------------------------------------------------- /xt/xpath/12_axis_descendant.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 4; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ENDXML 29 | 30 | 31 | my $set; 32 | $set = $x.find('/descendant::*'); 33 | is $set.elems, 11, 'found 11 elements'; 34 | 35 | $set = $x.find('/AAA/BBB/descendant::*'); 36 | is $set.elems, 4, 'found 4 elements'; 37 | 38 | $set = $x.find('//CCC/descendant::*'); 39 | is $set.elems, 6, 'found 5 elements'; 40 | 41 | $set = $x.find('//CCC/descendant::DDD'); 42 | is $set.elems, 3, 'found 3 elements'; 43 | 44 | done-testing; 45 | -------------------------------------------------------------------------------- /xt/xpath/13_axis_parent.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | ENDXML 14 | 15 | my $set; 16 | $set = $x.find('//DDD/parent::*'); 17 | is $set.elems, 4, 'found 1 elements'; 18 | is $set[3].name, 'EEE', '3th node is EEE'; 19 | 20 | done-testing; 21 | -------------------------------------------------------------------------------- /xt/xpath/14_axis_ancestor.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 11; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | ENDXML 14 | 15 | my $set; 16 | $set = .reverse given $x.find('/AAA/BBB/DDD/CCC/EEE/ancestor::*'); 17 | is $set.elems, 4, 'found 4 elements'; 18 | is $set[0].name, 'CCC', 'node is CCC'; 19 | is $set[1].name, 'DDD', 'node is EEE'; 20 | is $set[2].name, 'BBB', 'node is BBB'; 21 | is $set[3].name, 'AAA', 'node is AAA'; 22 | 23 | $set = .reverse given $x.find('//FFF/ancestor::*'); 24 | is $set.elems, 5, 'found 5 elements'; 25 | is $set[0].name, 'DDD', 'node is DDD'; 26 | is $set[1].name, 'EEE', 'node is EEE'; 27 | is $set[2].name, 'DDD', 'node is DDD'; 28 | is $set[3].name, 'CCC', 'node is CCC'; 29 | is $set[4].name, 'AAA', 'node is AAA'; 30 | 31 | done-testing; 32 | -------------------------------------------------------------------------------- /xt/xpath/15_axis_following_sibling.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 4; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | ENDXML 15 | 16 | my $set; 17 | $set = $x.find('/AAA/BBB/following-sibling::*'); 18 | is $set.elems, 2, 'found 2 elements'; 19 | is $set[1].name, 'CCC', 'node is CCC'; 20 | 21 | 22 | $set = $x.find('//CCC/following-sibling::*'); 23 | is $set.elems, 3, 'found 3 elements'; 24 | is $set[1].name, 'FFF', 'node is FFF'; 25 | 26 | done-testing; 27 | -------------------------------------------------------------------------------- /xt/xpath/16_axis_preceding-sibling.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Node; 6 | 7 | plan 5; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ENDXML 31 | 32 | my $set; 33 | $set = $x.find('/AAA/XXX/preceding-sibling::*'); 34 | 35 | isa-ok $set[0], LibXML::Node, 'found one node'; 36 | is $set[0].name, 'BBB', 'found node is BBB'; 37 | 38 | $set = $x.find('//CCC/preceding-sibling::*'); 39 | is $set.elems , 4, 'found four nodes'; 40 | 41 | $set = $x.find('/AAA/CCC/preceding-sibling::*[1]'); 42 | is $set[0].name , 'XXX', 'found node XXX'; 43 | 44 | $set = $x.find('/AAA/CCC/preceding-sibling::*[2]'); 45 | is $set[0].name , 'BBB', 'found node BBB'; 46 | 47 | done-testing; 48 | -------------------------------------------------------------------------------- /xt/xpath/17_axis_following.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ENDXML 38 | 39 | my $set; 40 | $set = $x.find('/AAA/XXX/following::*'); 41 | is $set.elems, 2 , 'found 2 nodes'; 42 | 43 | $set = $x.find('//ZZZ/following::*'); 44 | is $set.elems, 12 , 'found 2 nodes'; 45 | 46 | done-testing; 47 | -------------------------------------------------------------------------------- /xt/xpath/18_axis_preceding.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | ENDXML 32 | 33 | 34 | my $set; 35 | $set = $x.find('/AAA/XXX/preceding::*'); 36 | is $set.elems, 4, 'found 4 nodes'; 37 | 38 | $set = $x.find('//GGG/preceding::*'); 39 | is $set.elems, 8, 'found 8 nodes'; 40 | 41 | done-testing; 42 | -------------------------------------------------------------------------------- /xt/xpath/19_axis_descendant_or_self.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ENDXML 25 | 26 | my $set; 27 | $set = $x.find('/AAA/XXX/descendant-or-self::*'); 28 | is $set.elems, 8, 'found 8 nodes'; 29 | 30 | $set = $x.find('//CCC/descendant-or-self::*'); 31 | is $set.elems, 4, 'found 4 nodes'; 32 | 33 | done-testing; 34 | -------------------------------------------------------------------------------- /xt/xpath/20_axis_ancestor_or_self.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | ENDXML 15 | 16 | my $set; 17 | $set = $x.find('/AAA/XXX/DDD/EEE/ancestor-or-self::*'); 18 | is $set.elems, 4, 'found 4 nodes'; 19 | 20 | $set = $x.find('//GGG/ancestor-or-self::*'); 21 | is $set.elems, 5, 'found 5 nodes'; 22 | 23 | done-testing; 24 | -------------------------------------------------------------------------------- /xt/xpath/21_all_nodes.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Node; 6 | 7 | plan 15; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ENDXML 35 | 36 | my $set; 37 | $set = $x.find('//GGG/ancestor::*'); 38 | is $set.elems, 4, '4 ancestors'; 39 | 40 | $set = $x.find('//GGG/descendant::*'); 41 | is $set.elems, 3, '3 descendants'; 42 | 43 | $set = $x.find('//GGG/following::*'); 44 | is $set.elems, 3, '3 following'; 45 | is $set[0].name, 'VVV', '1st following is VVV'; 46 | is $set[1].name, 'CCC', '2nd following is CCC'; 47 | is $set[2].name, 'DDD', '3rd following is DDD'; 48 | 49 | $set = $x.find('//GGG/preceding::*'); 50 | is $set.elems, 5, '5 preceding'; 51 | # document order: BBB not HHH 52 | is $set[0].name, 'BBB', 'first following is BBB'; 53 | is $set[1].name, 'CCC', 'first following is CCC'; 54 | is $set[2].name, 'ZZZ', 'first following is ZZZ'; 55 | is $set[3].name, 'EEE', 'first following is EEE'; 56 | is $set[4].name, 'HHH', 'first following is HHH'; 57 | 58 | $set = $x.find('//GGG/self::*'); 59 | isa-ok $set[0] , LibXML::Node, '1 self'; 60 | is $set[0].name, 'GGG', 'first following is GGG'; 61 | 62 | $set = $x.find('//GGG/ancestor::* | //GGG/descendant::* | //GGG/following::* | //GGG/preceding::* | //GGG/self::*'); 63 | is $set.elems, 16, '16 nodes summary'; 64 | 65 | done-testing; 66 | 67 | -------------------------------------------------------------------------------- /xt/xpath/22_name_select.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 3; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ENDXML 18 | 19 | my $set; 20 | $set = $x.find('//*[ name() = /AAA/SELECT ]'); 21 | say "--"; 22 | say $set; 23 | is $set.elems, 2, '2 nodes'; 24 | is $set[0].name, 'BBB', 'name is BBB'; 25 | is $set[1].name, 'BBB', 'name is BBB'; 26 | 27 | done-testing; 28 | -------------------------------------------------------------------------------- /xt/xpath/23_much_more_function_and_expressions.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 7; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ENDXML 23 | 24 | my $set; 25 | $set = $x.find('//BBB[position()mod2=0]'); 26 | is $set.elems, 4, 'found 4 nodes'; 27 | 28 | $set = $x.find('//BBB[position()=floor(last()div2+0.5)orposition()=ceiling(last()div2+0.5)]'); 29 | is $set.elems, 2, 'found 2 nodes'; 30 | 31 | $set = $x.find('//CCC[position()=floor(last()div2+0.5)orposition()=ceiling(last()div2+0.5)]'); 32 | is $set.elems, 1, 'found 1 nodes'; 33 | 34 | $set = $x.find('//BBB[position()>=3]'); 35 | is $set.elems, 6, 'found 6 nodes'; 36 | 37 | $set = $x.find('//BBB[position()<=3]'); 38 | is $set.elems, 3, 'found 3 nodes'; 39 | 40 | $set = $x.find('//BBB[position()!=1 and position()!=3 and position()!=99]'); 41 | is $set.elems, 6, 'found 6 nodes'; 42 | 43 | $set = $x.find('//BBB[position()*2 mod 3=0]'); 44 | is $set.elems, 2, 'found 2 nodes'; 45 | 46 | 47 | done-testing; 48 | -------------------------------------------------------------------------------- /xt/xpath/24_namespaces.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 9; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | ENDXML 25 | 26 | $x .= xpath-context; 27 | # Don't set namespace prefixes - uses element context namespaces 28 | my $set; 29 | 30 | $set = $x.find('//foo:foo'); 31 | is $set.elems, 3, 'found 3 nodes'; 32 | 33 | dies-ok {$set = $x.find('//goo:foo')}; 34 | ##is $set.elems, 0, 'found 0 nodes'; 35 | 36 | # all nodes are in the 'flubber' namespace 37 | $set = $x.find('//foo'); 38 | is $set.elems, 0, 'found 0 nodes'; 39 | 40 | $set = $x.find('//*'); 41 | is $set.elems, 10, 'found 10 nodes'; 42 | 43 | $set = $x.find('//foo:*'); 44 | is $set.elems, 5, 'found 5 nodes with the ns foo'; 45 | 46 | dies-ok {$set = $x.find('//@attr:*');} 47 | ##is $set.elems, 1, 'found one attribute'; 48 | 49 | # Set namespace prefixes 50 | $x.registerNs('goo', 'http://foobar.example.com'); 51 | $x.registerNs('foo', 'http://flubber.example.com'); 52 | 53 | # should find flubber.com foos 54 | $set = $x.find('//foo:foo'); 55 | is $set.elems, 2, 'found 3 nodes'; 56 | 57 | # should find foobar.com foos 58 | $set = $x.find('//goo:foo'); 59 | is $set.elems, 3, 'found 0 nodes'; 60 | 61 | # shouldn't find NS foos in flubber namespace 62 | $set = $x.find('/foo'); 63 | is $set.elems, 0, 'found 2 nodes'; 64 | 65 | done-testing; 66 | -------------------------------------------------------------------------------- /xt/xpath/26_predicate.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | some 1 12 | value 1 13 | 14 | 15 | some 2 16 | value 2 17 | 18 | 19 | ENDXML 20 | 21 | my $set; 22 | $set = $x.find('//a/b[2]'); 23 | is $set.elems, 2, 'found 2 nodes'; 24 | 25 | # value 1 26 | $set = $x.find('(//a/b)[2]'); 27 | is $set.elems, 1, 'found 1 nodes'; 28 | 29 | done-testing; 30 | 31 | -------------------------------------------------------------------------------- /xt/xpath/28_ancestor2.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Element; 6 | 7 | plan 3; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | 12 | 2 13 | 14 | AxKit 16 | is very flexible in how it lets you transform the XML on the 17 | server, and there are many modules you can plug in to AxKit to 18 | allow you to do these transformations. For this reason, the AxKit 19 | installation does not mandate any particular modules to use, 20 | instead it will simply suggest modules that might help when you 21 | install AxKit. 22 | 23 | 24 | 25 | ENDXML 26 | 27 | my $set; 28 | my $footnote = $x.first('//Footnote'); 29 | isa-ok $footnote, LibXML::Element, 'found a node'; 30 | 31 | 32 | $set = $x.find('ancestor::*', $footnote); 33 | is $set.elems, 3, 'last match has 3 ancestors'; 34 | 35 | $set = $x.find('ancestor::text:footnote', $footnote); 36 | isa-ok $set[0], LibXML::Element, 'found one text::footnote'; 37 | 38 | done-testing; 39 | 40 | -------------------------------------------------------------------------------- /xt/xpath/29_desc_with_predicate.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Element; 6 | use LibXML::Text; 7 | 8 | plan 4; 9 | 10 | my $x = LibXML.parse(string => q:to/ENDXML/); 11 | 12 | OK 13 | 14 | 15 | 16 | NOT OK 17 | 18 | ENDXML 19 | 20 | my $set; 21 | $set = $x.find('/descendant::BBB[1]'); 22 | isa-ok $set[0], LibXML::Element, 'found one node'; 23 | is $set[0].nodes.elems, 1, 'one child'; 24 | isa-ok $set[0].nodes[0], LibXML::Text, 'child is a text node'; 25 | is $set[0].nodes[0].Str, 'OK', 'it is OK'; 26 | 27 | done-testing; 28 | -------------------------------------------------------------------------------- /xt/xpath/30_lang.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | Here we go... 11 | und hier deutschsprachiger Text :-) 12 | 13 | ENDXML 14 | 15 | my $set; 16 | $set = $x.find('//*[ lang("en")]'); 17 | is $set.elems, 2, 'found 2 english nodes'; 18 | 19 | $set = $x.find('//content[ lang("de") ]', :to-list(True)); 20 | is $set.elems, 1, 'found 1 german node'; 21 | 22 | done-testing; 23 | -------------------------------------------------------------------------------- /xt/xpath/31_dots.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | use LibXML::Document; 6 | 7 | plan 2; 8 | 9 | my $x = LibXML.parse(string => q:to/ENDXML/); 10 | 11 | ENDXML 12 | 13 | my $set; 14 | my $root = $x.first('/.'); 15 | isa-ok $root, LibXML::Document, 'found one node'; 16 | 17 | my $doc = $x.first('/..'); 18 | nok $doc.defined, 'nothing found'; 19 | 20 | done-testing; 21 | -------------------------------------------------------------------------------- /xt/xpath/35_namespace_uri.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 1; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | 15 | ENDXML 16 | 17 | my $nodes = $x.find("//*[ namespace-uri() = 'http://foobar.example.com' ]"); 18 | is $nodes.elems, 4, 'found 4 nodes'; 19 | 20 | done-testing; 21 | -------------------------------------------------------------------------------- /xt/xpath/36_substring.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 11; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | ENDXML 11 | 12 | is $x.find('substring("12345", 2, 3)'), "234"; 13 | is $x.find('substring("12345", 2)'), "2345"; 14 | is $x.find('substring("12345", -2)'), "12345"; 15 | is $x.find('substring("12345", 1.5, 2.6)'), "234"; 16 | is $x.find('substring("12345", 0 div 0, 3)'), ""; 17 | is $x.find('substring("12345", 1, 0 div 0)'), ""; 18 | is $x.find('substring("12345", -1 div 0, 1 div 0)'), ""; 19 | is $x.find('substring("12345", -42, 1 div 0)'), "12345"; 20 | is $x.find('substring("12345", 0, 1 div 0)'), "12345"; 21 | is $x.find('substring("12345", 0, 3)'), "12"; 22 | is $x.find('substring("12345", -1, 4)'), "12"; 23 | 24 | done-testing 25 | -------------------------------------------------------------------------------- /xt/xpath/37_concat.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 |

    10 | Hello 11 | World 12 |

    13 | ENDXML 14 | 15 | is $x.find('concat("1", "2", "3")'), "123", "123"; 16 | is $x.find('concat( /p/element4/text(), /p/element5/text() )'), 'HelloWorld', 'HelloWorld'; 17 | 18 | done-testing; 19 | -------------------------------------------------------------------------------- /xt/xpath/38_starts_with.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 2; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | ENDXML 11 | 12 | is $x.find('starts-with("123","1")'), True, "123 starts with 1"; 13 | is $x.find('starts-with("123","23")'), False, "123 starts not with 23"; 14 | 15 | done-testing; 16 | -------------------------------------------------------------------------------- /xt/xpath/39_contains.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 3; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | ENDXML 11 | 12 | is $x.find('contains("123","1")'), True, '"123" contains "1"'; 13 | is $x.find('contains("123","4")'), False,'"123" does not contain "4"'; 14 | is $x.find('contains(/foo/@num,"1")'), True, 'XML Attribute num contains "1"'; 15 | 16 | 17 | done-testing; 18 | -------------------------------------------------------------------------------- /xt/xpath/40_substring_before.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 3; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | ENDXML 11 | 12 | is $x.find('substring-before("1999/04/01","/")'), '1999'; 13 | is $x.find('substring-before(/foo/@num,"o")'), 'f'; 14 | is $x.find('substring-before("1999/04/01","?")'), ''; 15 | 16 | done-testing; 17 | -------------------------------------------------------------------------------- /xt/xpath/41_substring_after.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 4; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | ENDXML 11 | 12 | is $x.find('substring-after("1999/04/01","/")'), '04/01'; 13 | is $x.find('substring-after("1999/04/01","19")'), '99/04/01'; 14 | is $x.find('substring-after("1999/04/01","2")'), ''; 15 | is $x.find('substring-after(/foo/@num,"x")'), ''; 16 | 17 | done-testing; 18 | -------------------------------------------------------------------------------- /xt/xpath/43_op_div.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 7; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 |

    10 | ENDXML 11 | 12 | is $x.find('-4'), -4, "-4 == -4"; 13 | is $x.find('-4 div 1'), -4, "-4 div 1 == -4"; 14 | is $x.find('4 div 2'), 2, "4 div 2 == 2"; 15 | is $x.find('4 div 0'), Inf, "4 div 0 == Inf"; 16 | is $x.find('-4 div 0'), -Inf, "-4 div 0 == -Inf"; 17 | is $x.find('0 div 0'), NaN, "0 div 0 == NaN"; 18 | is $x.find('0 div 2'), 0, "0 div 2 == 0"; 19 | 20 | done-testing; 21 | -------------------------------------------------------------------------------- /xt/xpath/44_test_compare.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 6; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | 12 | 13 | 14 | ENDXML 15 | 16 | # my %results= ( '/root/daughter[@att<"4"]' => 'daughter[3]', 17 | # '/root/daughter[@att<4]' => 'daughter[3]', 18 | # '//daughter[@att<4]' => 'daughter[3]', 19 | # '/root/daughter[@att>4]' => 'daughter[5]', 20 | # '/root/daughter[@att>5]' => '', 21 | # '/root/daughter[@att<3]' => '', 22 | # ); 23 | is $x.first('/root/daughter[@att<"4"]').attribs , 3; 24 | is $x.first('/root/daughter[@att<4]').attribs , 3; 25 | is $x.first('//daughter[@att<4]').attribs , 3; 26 | is $x.first('/root/daughter[@att>4]').attribs , 5; 27 | 28 | is $x.find('/root/daughter[@att>5]'), ''; 29 | is $x.find('/root/daughter[@att<3]'), ''; 30 | 31 | done-testing; 32 | -------------------------------------------------------------------------------- /xt/xpath/46_context.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 1; 7 | 8 | my $x = LibXML.parse(string => q:to/ENDXML/); 9 | 10 | 11 | I start the text here, I break 12 | the line and I go on, I twinkle and then I go on 13 | again. 14 | This is not a new paragraph. 15 | 16 | 17 | This is a 18 | new paragraph and 19 | this word has a preceding sibling. 20 | 21 | 22 | ENDXML 23 | 24 | my $set1 = $x.find("text/para/node()[position()=last() and preceding-sibling::important]"); 25 | my $set2 = $x.find("text/para/node()[preceding-sibling::important and position()=last()]"); 26 | 27 | ok $set1.is-equiv($set2),'both expressions are the same'; 28 | 29 | done-testing(); 30 | -------------------------------------------------------------------------------- /xt/xpath/48_translate.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | plan 4; 7 | 8 | my $x = LibXML.parse(string => ''); 9 | is $x.find('translate("1,234.56", ",", "")'), 1234.56; 10 | is $x.find('translate("bar", "abc", "ABC")'), "BAr"; 11 | is $x.find('translate("--aaa--", "abc-", "ABC")'), "AAA"; 12 | 13 | # If a character occurs more than once in the second argument string, then the first occurrence determines the replacement character. 14 | is $x.find('translate("--aaa--", "abca-", "ABCX")'), "AAA"; 15 | 16 | done-testing(); 17 | -------------------------------------------------------------------------------- /xt/xpath/50_issue_9.t: -------------------------------------------------------------------------------- 1 | use v6.c; 2 | 3 | use Test; 4 | use LibXML; 5 | 6 | my $x = LibXML.parse(string => 'link descyada yada'); 7 | my $lnk = $x.first('//a',); 8 | my @t := $x.find('//text()', $lnk); 9 | 10 | is @t.elems, 2, 'found two elements'; 11 | is @t[0].text, 'link desc', 'found link desc'; 12 | is @t[1].text, 'yada yada', 'found yada yada'; 13 | 14 | done-testing; 15 | 16 | -------------------------------------------------------------------------------- /xt/xpath/README: -------------------------------------------------------------------------------- 1 | Tests courtesy of the Raku XML::Path module. 2 | --------------------------------------------------------------------------------