Newer
Older
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
<span class="tok-c1">// copy the document above the include directive (this retains the original order!)</span>
<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">ic</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">ic</span><span class="tok-p">;</span> <span class="tok-n">ic</span> <span class="tok-o">=</span> <span class="tok-n">ic</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
<span class="tok-p">{</span>
<span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">insert_copy_before</span><span class="tok-p">(</span><span class="tok-n">ic</span><span class="tok-p">,</span> <span class="tok-n">include</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-c1">// remove the include node and move to the next child</span>
<span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">();</span>
<span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">remove_child</span><span class="tok-p">(</span><span class="tok-n">include</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-k">else</span>
<span class="tok-p">{</span>
<span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-o">!</span><span class="tok-n">preprocess</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">))</span> <span class="tok-k">return</span> <span class="tok-nb">false</span><span class="tok-p">;</span>
<span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">();</span>
<span class="tok-p">}</span>
<span class="tok-p">}</span>
<span class="tok-k">return</span> <span class="tok-nb">true</span><span class="tok-p">;</span>
<span class="tok-p">}</span>
<span class="tok-kt">bool</span> <span class="tok-nf">load_preprocess</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-o">&</span> <span class="tok-n">doc</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_parse_result</span> <span class="tok-n">result</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_file</span><span class="tok-p">(</span><span class="tok-n">path</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">parse_default</span> <span class="tok-o">|</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">parse_pi</span><span class="tok-p">);</span> <span class="tok-c1">// for <?include?></span>
<span class="tok-k">return</span> <span class="tok-n">result</span> <span class="tok-o">?</span> <span class="tok-n">preprocess</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">)</span> <span class="tok-o">:</span> <span class="tok-nb">false</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="modify.move"><a class="anchor" href="#modify.move"></a>6.7. Moving nodes</h3>
<div class="paragraph">
<p><a id="xml_node::prepend_move"></a><a id="xml_node::append_move"></a><a id="xml_node::insert_move_after"></a><a id="xml_node::insert_move_before"></a>
Sometimes instead of cloning a node you need to move an existing node to a different position in a tree. This can be accomplished by copying the node and removing the original; however, this is expensive since it results in a lot of extra operations. For moving nodes within the same document tree, you can use of the following functions instead:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">append_move</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&</span> <span class="tok-n">moved</span><span class="tok-p">);</span>
<span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">prepend_move</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&</span> <span class="tok-n">moved</span><span class="tok-p">);</span>
<span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">insert_move_after</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&</span> <span class="tok-n">moved</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&</span> <span class="tok-n">node</span><span class="tok-p">);</span>
<span class="tok-n">xml_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">insert_move_before</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&</span> <span class="tok-n">moved</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xml_node</span><span class="tok-o">&</span> <span class="tok-n">node</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions mirror the structure of <code>append_copy</code>, <code>prepend_copy</code>, <code>insert_copy_before</code> and <code>insert_copy_after</code> - they take the handle to the moved object and move it to the appropriate place with all attributes and/or child nodes. The functions return the handle to the resulting object (which is the same as the moved object), or null handle on failure.</p>
</div>
<div class="paragraph">
<p>The failure conditions resemble those of <code>append_child</code>, <code>insert_child_before</code> and related functions, <a href="#xml_node::append_child">consult their documentation for more information</a>. There are additional caveats specific to moving functions:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Moving null handles results in operation failure;</p>
</li>
<li>
<p>Moving is only possible for nodes that belong to the same document; attempting to move nodes between documents will fail.</p>
</li>
<li>
<p><code>insert_move_after</code> and <code>insert_move_before</code> functions fail if the moved node is the same as the <code>node</code> argument (this operation would be a no-op otherwise).</p>
</li>
<li>
<p>It is impossible to move a subtree to a child of some node inside this subtree, i.e. <code>node.append_move(node.parent().parent());</code> will fail.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="modify.fragments"><a class="anchor" href="#modify.fragments"></a>6.8. Assembling document from fragments</h3>
<div id="xml_node::append_buffer" class="paragraph">
<p>pugixml provides several ways to assemble an XML document from other XML documents. Assuming there is a set of document fragments, represented as in-memory buffers, the implementation choices are as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Use a temporary document to parse the data from a string, then clone the nodes to a destination node. For example:</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-nf">append_fragment</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">target</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">buffer</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-o">!</span><span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_buffer</span><span class="tok-p">(</span><span class="tok-n">buffer</span><span class="tok-p">,</span> <span class="tok-n">size</span><span class="tok-p">))</span> <span class="tok-k">return</span> <span class="tok-nb">false</span><span class="tok-p">;</span>
<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">child</span><span class="tok-p">;</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
<span class="tok-n">target</span><span class="tok-p">.</span><span class="tok-n">append_copy</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">);</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</li>
<li>
<p>Cache the parsing step - instead of keeping in-memory buffers, keep document objects that already contain the parsed fragment:</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-nf">append_fragment</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">target</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span><span class="tok-o">&</span> <span class="tok-n">cached_fragment</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">cached_fragment</span><span class="tok-p">.</span><span class="tok-n">first_child</span><span class="tok-p">();</span> <span class="tok-n">child</span><span class="tok-p">;</span> <span class="tok-n">child</span> <span class="tok-o">=</span> <span class="tok-n">child</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
<span class="tok-n">target</span><span class="tok-p">.</span><span class="tok-n">append_copy</span><span class="tok-p">(</span><span class="tok-n">child</span><span class="tok-p">);</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</li>
<li>
<p>Use <code>xml_node::append_buffer</code> directly:</p>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xml_parse_result</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">append_buffer</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">void</span><span class="tok-o">*</span> <span class="tok-n">contents</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">options</span> <span class="tok-o">=</span> <span class="tok-n">parse_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>The first method is more convenient, but slower than the other two. The relative performance of <code>append_copy</code> and <code>append_buffer</code> depends on the buffer format - usually <code>append_buffer</code> is faster if the buffer is in native encoding (UTF-8 or wchar_t, depending on <code>PUGIXML_WCHAR_MODE</code>). At the same time it might be less efficient in terms of memory usage - the implementation makes a copy of the provided buffer, and the copy has the same lifetime as the document - the memory used by that copy will be reclaimed after the document is destroyed, but no sooner. Even deleting all nodes in the document, including the appended ones, won’t reclaim the memory.</p>
</div>
<div class="paragraph">
<p><code>append_buffer</code> behaves in the same way as <a href="#xml_document::load_buffer">xml_document::load_buffer</a> - the input buffer is a byte buffer, with size in bytes; the buffer is not modified and can be freed after the function returns.</p>
</div>
<div id="status_append_invalid_root" class="paragraph">
<p>Since <code>append_buffer</code> needs to append child nodes to the current node, it only works if the current node is either document or element node. Calling <code>append_buffer</code> on a node with any other type results in an error with <code>status_append_invalid_root</code> status.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="saving"><a class="anchor" href="#saving"></a>7. Saving document</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Often after creating a new document or loading the existing one and processing it, it is necessary to save the result back to file. Also it is occasionally useful to output the whole document or a subtree to some stream; use cases include debug printing, serialization via network or other text-oriented medium, etc. pugixml provides several functions to output any subtree of the document to a file, stream or another generic transport interface; these functions allow to customize the output format (see <a href="#saving.options">Output options</a>), and also perform necessary encoding conversions (see <a href="#saving.encoding">Encodings</a>). This section documents the relevant functionality.</p>
</div>
<div class="paragraph">
<p>Before writing to the destination the node/attribute data is properly formatted according to the node type; all special XML symbols, such as <code><</code> and <code>&</code>, are properly escaped (unless <a href="#format_no_escapes">format_no_escapes</a> flag is set). In order to guard against forgotten node/attribute names, empty node/attribute names are printed as <code>":anonymous"</code>. For well-formed output, make sure all node and attribute names are set to meaningful values.</p>
</div>
<div class="paragraph">
<p>CDATA sections with values that contain <code>"]]>"</code> are split into several sections as follows: section with value <code>"pre]]>post"</code> is written as <code><![CDATA[pre]]]]><![CDATA[>post]]></code>. While this alters the structure of the document (if you load the document after saving it, there will be two CDATA sections instead of one), this is the only way to escape CDATA contents.</p>
</div>
<div class="sect2">
<h3 id="saving.file"><a class="anchor" href="#saving.file"></a>7.1. Saving document to a file</h3>
<div class="paragraph">
<p><a id="xml_document::save_file"></a><a id="xml_document::save_file_wide"></a>
If you want to save the whole document to a file, you can use one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">bool</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">wchar_t</span><span class="tok-o">*</span> <span class="tok-n">path</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions accept file path as its first argument, and also three optional arguments, which specify indentation and other output options (see <a href="#saving.options">Output options</a>) and output data encoding (see <a href="#saving.encoding">Encodings</a>). The path has the target operating system format, so it can be a relative or absolute one, it should have the delimiters of the target system, it should have the exact case if the target file system is case-sensitive, etc.</p>
</div>
<div class="paragraph">
<p>File path is passed to the system file opening function as is in case of the first function (which accepts <code>const char* path</code>); the second function either uses a special file opening function if it is provided by the runtime library or converts the path to UTF-8 and uses the system file opening function.</p>
</div>
<div id="xml_writer_file" class="paragraph">
<p><code>save_file</code> opens the target file for writing, outputs the requested header (by default a document declaration is output, unless the document already has one), and then saves the document contents. If the file could not be opened, the function returns <code>false</code>. Calling <code>save_file</code> is equivalent to creating an <code>xml_writer_file</code> object with <code>FILE*</code> handle as the only constructor argument and then calling <code>save</code>; see <a href="#saving.writer">Saving document via writer interface</a> for writer interface details.</p>
</div>
<div class="paragraph">
<p>This is a simple example of saving XML document to file (<a href="samples/save_file.cpp" class="bare">samples/save_file.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// save document to file</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Saving result: "</span> <span class="tok-o"><<</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save_file</span><span class="tok-p">(</span><span class="tok-s">"save_file_output.xml"</span><span class="tok-p">)</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.stream"><a class="anchor" href="#saving.stream"></a>7.2. Saving document to C++ IOstreams</h3>
<div id="xml_document::save_stream" class="paragraph">
<p>To enhance interoperability pugixml provides functions for saving document to any object which implements C++ <code>std::ostream</code> interface. This allows you to save documents to any standard C++ stream (i.e. file stream) or any third-party compliant implementation (i.e. Boost Iostreams). Most notably, this allows for easy debug output, since you can use <code>std::cout</code> stream as saving target. There are two functions, one works with narrow character streams, another handles wide character ones:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">void</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">ostream</span><span class="tok-o">&</span> <span class="tok-n">stream</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">wostream</span><span class="tok-o">&</span> <span class="tok-n">stream</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>save</code> with <code>std::ostream</code> argument saves the document to the stream in the same way as <code>save_file</code> (i.e. with requested header and with encoding conversions). On the other hand, <code>save</code> with <code>std::wstream</code> argument saves the document to the wide stream with <a href="#encoding_wchar">encoding_wchar</a> encoding. Because of this, using <code>save</code> with wide character streams requires careful (usually platform-specific) stream setup (i.e. using the <code>imbue</code> function). Generally use of wide streams is discouraged, however it provides you with the ability to save documents to non-Unicode encodings, i.e. you can save Shift-JIS encoded data if you set the correct locale.</p>
</div>
<div id="xml_writer_stream" class="paragraph">
<p>Calling <code>save</code> with stream target is equivalent to creating an <code>xml_writer_stream</code> object with stream as the only constructor argument and then calling <code>save</code>; see <a href="#saving.writer">Saving document via writer interface</a> for writer interface details.</p>
</div>
<div class="paragraph">
<p>This is a simple example of saving XML document to standard output (<a href="samples/save_stream.cpp" class="bare">samples/save_stream.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// save document to standard output</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Document:</span><span class="tok-se">\n</span><span class="tok-s">"</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.writer"><a class="anchor" href="#saving.writer"></a>7.3. Saving document via writer interface</h3>
<div class="paragraph">
<p><a id="xml_document::save"></a><a id="xml_writer"></a><a id="xml_writer::write"></a>
All of the above saving functions are implemented in terms of writer interface. This is a simple interface with a single function, which is called several times during output process with chunks of document data as input:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">class</span> <span class="tok-nc">xml_writer</span>
<span class="tok-p">{</span>
<span class="tok-k">public</span><span class="tok-o">:</span>
<span class="tok-k">virtual</span> <span class="tok-kt">void</span> <span class="tok-n">write</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">void</span><span class="tok-o">*</span> <span class="tok-n">data</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">;</span>
<span class="tok-p">};</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_document</span><span class="tok-o">::</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">xml_writer</span><span class="tok-o">&</span> <span class="tok-n">writer</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>In order to output the document via some custom transport, for example sockets, you should create an object which implements <code>xml_writer</code> interface and pass it to <code>save</code> function. <code>xml_writer::write</code> function is called with a buffer as an input, where <code>data</code> points to buffer start, and <code>size</code> is equal to the buffer size in bytes. <code>write</code> implementation must write the buffer to the transport; it can not save the passed buffer pointer, as the buffer contents will change after <code>write</code> returns. The buffer contains the chunk of document data in the desired encoding.</p>
</div>
<div class="paragraph">
<p><code>write</code> function is called with relatively large blocks (size is usually several kilobytes, except for the last block that may be small), so there is often no need for additional buffering in the implementation.</p>
</div>
<div class="paragraph">
<p>This is a simple example of custom writer for saving document data to STL string (<a href="samples/save_custom_writer.cpp" class="bare">samples/save_custom_writer.cpp</a>); read the sample code for more complex examples:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">struct</span> <span class="tok-nl">xml_string_writer</span><span class="tok-p">:</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_writer</span>
<span class="tok-p">{</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">string</span> <span class="tok-n">result</span><span class="tok-p">;</span>
<span class="tok-k">virtual</span> <span class="tok-kt">void</span> <span class="tok-nf">write</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">void</span><span class="tok-o">*</span> <span class="tok-n">data</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">size</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">result</span><span class="tok-p">.</span><span class="tok-n">append</span><span class="tok-p">(</span><span class="tok-k">static_cast</span><span class="tok-o"><</span><span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*></span><span class="tok-p">(</span><span class="tok-n">data</span><span class="tok-p">),</span> <span class="tok-n">size</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.subtree"><a class="anchor" href="#saving.subtree"></a>7.4. Saving a single subtree</h3>
<div class="paragraph">
<p><a id="xml_node::print"></a><a id="xml_node::print_stream"></a>
While the previously described functions save the whole document to the destination, it is easy to save a single subtree. The following functions are provided:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">void</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">ostream</span><span class="tok-o">&</span> <span class="tok-n">os</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">depth</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">wostream</span><span class="tok-o">&</span> <span class="tok-n">os</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">depth</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">void</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">xml_writer</span><span class="tok-o">&</span> <span class="tok-n">writer</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">indent</span> <span class="tok-o">=</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">flags</span> <span class="tok-o">=</span> <span class="tok-n">format_default</span><span class="tok-p">,</span> <span class="tok-n">xml_encoding</span> <span class="tok-n">encoding</span> <span class="tok-o">=</span> <span class="tok-n">encoding_auto</span><span class="tok-p">,</span> <span class="tok-kt">unsigned</span> <span class="tok-kt">int</span> <span class="tok-n">depth</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions have the same arguments with the same meaning as the corresponding <code>xml_document::save</code> functions, and allow you to save the subtree to either a C++ IOstream or to any object that implements <code>xml_writer</code> interface.</p>
</div>
<div class="paragraph">
<p>Saving a subtree differs from saving the whole document: the process behaves as if <a href="#format_write_bom">format_write_bom</a> is off, and <a href="#format_no_declaration">format_no_declaration</a> is on, even if actual values of the flags are different. This means that BOM is not written to the destination, and document declaration is only written if it is the node itself or is one of node’s children. Note that this also holds if you’re saving a document; this example (<a href="samples/save_subtree.cpp" class="bare">samples/save_subtree.cpp</a>) illustrates the difference:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// get a test document</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-s">"<foo bar='baz'><call>hey</call></foo>"</span><span class="tok-p">);</span>
<span class="tok-c1">// print document to standard output (prints <?xml version="1.0"?><foo bar="baz"><call>hey</call></foo>)</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">""</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// print document to standard output as a regular node (prints <foo bar="baz"><call>hey</call></foo>)</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">""</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// print a subtree to standard output (prints <call>hey</call>)</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">"foo"</span><span class="tok-p">).</span><span class="tok-n">child</span><span class="tok-p">(</span><span class="tok-s">"call"</span><span class="tok-p">).</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">""</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.options"><a class="anchor" href="#saving.options"></a>7.5. Output options</h3>
<div class="paragraph">
<p>All saving functions accept the optional parameter <code>flags</code>. This is a bitmask that customizes the output format; you can select the way the document nodes are printed and select the needed additional information that is output before the document contents.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
You should use the usual bitwise arithmetics to manipulate the bitmask: to enable a flag, use <code>mask | flag</code>; to disable a flag, use <code>mask & ~flag</code>.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>These flags control the resulting tree contents:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a id="format_indent"></a><code>format_indent</code> determines if all nodes should be indented with the indentation string (this is an additional parameter for all saving functions, and is <code>"\t"</code> by default). If this flag is on, before every node the indentation string is output several times, where the amount of indentation depends on the node’s depth relative to the output subtree. This flag has no effect if <a href="#format_raw">format_raw</a> is enabled. This flag is <strong>on</strong> by default.</p>
</li>
<li>
<p><a id="format_raw"></a><code>format_raw</code> switches between formatted and raw output. If this flag is on, the nodes are not indented in any way, and also no newlines that are not part of document text are printed. Raw mode can be used for serialization where the result is not intended to be read by humans; also it can be useful if the document was parsed with <a href="#parse_ws_pcdata">parse_ws_pcdata</a> flag, to preserve the original document formatting as much as possible. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_no_escapes"></a><code>format_no_escapes</code> disables output escaping for attribute values and PCDATA contents. If this flag is off, special symbols (<code>"</code>, <code>&</code>, <code><</code>, <code>></code>) and all non-printable characters (those with codepoint values less than 32) are converted to XML escape sequences (i.e. <code>&amp;</code>) during output. If this flag is on, no text processing is performed; therefore, output XML can be malformed if output contents contains invalid symbols (i.e. having a stray <code><</code> in the PCDATA will make the output malformed). This flag is <strong>off</strong> by default.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>These flags control the additional output information:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a id="format_no_declaration"></a><code>format_no_declaration</code> disables default node declaration output. By default, if the document is saved via <code>save</code> or <code>save_file</code> function, and it does not have any document declaration, a default declaration is output before the document contents. Enabling this flag disables this declaration. This flag has no effect in <code>xml_node::print</code> functions: they never output the default declaration. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_write_bom"></a><code>format_write_bom</code> enables Byte Order Mark (BOM) output. By default, no BOM is output, so in case of non UTF-8 encodings the resulting document’s encoding may not be recognized by some parsers and text editors, if they do not implement sophisticated encoding detection. Enabling this flag adds an encoding-specific BOM to the output. This flag has no effect in <code>xml_node::print</code> functions: they never output the BOM. This flag is <strong>off</strong> by default.</p>
</li>
<li>
<p><a id="format_save_file_text"></a><code>format_save_file_text</code> changes the file mode when using <code>save_file</code> function. By default, file is opened in binary mode, which means that the output file will
contain platform-independent newline <code>\n</code> (ASCII 10). If this flag is on, file is opened in text mode, which on some systems changes the newline format (i.e. on Windows you can use this flag to output XML documents with <code>\r\n</code> (ASCII 13 10) newlines. This flag is <strong>off</strong> by default.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Additionally, there is one predefined option mask:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a id="format_default"></a><code>format_default</code> is the default set of flags, i.e. it has all options set to their default values. It sets formatted output with indentation, without BOM and with default node declaration, if necessary.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This is an example that shows the outputs of different output options (<a href="samples/save_options.cpp" class="bare">samples/save_options.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// get a test document</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-s">"<foo bar='baz'><call>hey</call></foo>"</span><span class="tok-p">);</span>
<span class="tok-c1">// default options; prints</span>
<span class="tok-c1">// <?xml version="1.0"?></span>
<span class="tok-c1">// <foo bar="baz"></span>
<span class="tok-c1">// <call>hey</call></span>
<span class="tok-c1">// </foo></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// default options with custom indentation string; prints</span>
<span class="tok-c1">// <?xml version="1.0"?></span>
<span class="tok-c1">// <foo bar="baz"></span>
<span class="tok-c1">// --<call>hey</call></span>
<span class="tok-c1">// </foo></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">"--"</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// default options without indentation; prints</span>
<span class="tok-c1">// <?xml version="1.0"?></span>
<span class="tok-c1">// <foo bar="baz"></span>
<span class="tok-c1">// <call>hey</call></span>
<span class="tok-c1">// </foo></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_default</span> <span class="tok-o">&</span> <span class="tok-o">~</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_indent</span><span class="tok-p">);</span> <span class="tok-c1">// can also pass "" instead of indentation string for the same effect</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// raw output; prints</span>
<span class="tok-c1">// <?xml version="1.0"?><foo bar="baz"><call>hey</call></foo></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// raw output without declaration; prints</span>
<span class="tok-c1">// <foo bar="baz"><call>hey</call></foo></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">,</span> <span class="tok-s">"</span><span class="tok-se">\t</span><span class="tok-s">"</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_raw</span> <span class="tok-o">|</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">format_no_declaration</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="saving.encoding"><a class="anchor" href="#saving.encoding"></a>7.6. Encodings</h3>
<div class="paragraph">
<p>pugixml supports all popular Unicode encodings (UTF-8, UTF-16 (big and little endian), UTF-32 (big and little endian); UCS-2 is naturally supported since it’s a strict subset of UTF-16) and handles all encoding conversions during output. The output encoding is set via the <code>encoding</code> parameter of saving functions, which is of type <code>xml_encoding</code>. The possible values for the encoding are documented in <a href="#loading.encoding">Encodings</a>; the only flag that has a different meaning is <code>encoding_auto</code>.</p>
</div>
<div class="paragraph">
<p>While all other flags set the exact encoding, <code>encoding_auto</code> is meant for automatic encoding detection. The automatic detection does not make sense for output encoding, since there is usually nothing to infer the actual encoding from, so here <code>encoding_auto</code> means UTF-8 encoding, which is the most popular encoding for XML data storage. This is also the default value of output encoding; specify another value if you do not want UTF-8 encoded output.</p>
</div>
<div class="paragraph">
<p>Also note that wide stream saving functions do not have <code>encoding</code> argument and always assume <a href="#encoding_wchar">encoding_wchar</a> encoding.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The current behavior for Unicode conversion is to skip all invalid UTF sequences during conversion. This behavior should not be relied upon; if your node/attribute names do not contain any valid UTF sequences, they may be output as if they are empty, which will result in malformed XML document.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="saving.declaration"><a class="anchor" href="#saving.declaration"></a>7.7. Customizing document declaration</h3>
<div class="paragraph">
<p>When you are saving the document using <code>xml_document::save()</code> or <code>xml_document::save_file()</code>, a default XML document declaration is output, if <code>format_no_declaration</code> is not specified and if the document does not have a declaration node. However, the default declaration is not customizable. If you want to customize the declaration output, you need to create the declaration node yourself.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
By default the declaration node is not added to the document during parsing. If you just need to preserve the original declaration node, you have to add the flag <a href="#parse_declaration">parse_declaration</a> to the parsing flags; the resulting document will contain the original declaration node, which will be output during saving.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Declaration node is a node with type <a href="#node_declaration">node_declaration</a>; it behaves like an element node in that it has attributes with values (but it does not have child nodes). Therefore setting custom version, encoding or standalone declaration involves adding attributes and setting attribute values.</p>
</div>
<div class="paragraph">
<p>This is an example that shows how to create a custom declaration node (<a href="samples/save_declaration.cpp" class="bare">samples/save_declaration.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// get a test document</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_document</span> <span class="tok-n">doc</span><span class="tok-p">;</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">load_string</span><span class="tok-p">(</span><span class="tok-s">"<foo bar='baz'><call>hey</call></foo>"</span><span class="tok-p">);</span>
<span class="tok-c1">// add a custom declaration node</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">decl</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">prepend_child</span><span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">node_declaration</span><span class="tok-p">);</span>
<span class="tok-n">decl</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">"version"</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-s">"1.0"</span><span class="tok-p">;</span>
<span class="tok-n">decl</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">"encoding"</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-s">"UTF-8"</span><span class="tok-p">;</span>
<span class="tok-n">decl</span><span class="tok-p">.</span><span class="tok-n">append_attribute</span><span class="tok-p">(</span><span class="tok-s">"standalone"</span><span class="tok-p">)</span> <span class="tok-o">=</span> <span class="tok-s">"no"</span><span class="tok-p">;</span>
<span class="tok-c1">// <?xml version="1.0" encoding="UTF-8" standalone="no"?></span>
<span class="tok-c1">// <foo bar="baz"></span>
<span class="tok-c1">// <call>hey</call></span>
<span class="tok-c1">// </foo></span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">save</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="xpath"><a class="anchor" href="#xpath"></a>8. XPath</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If the task at hand is to select a subset of document nodes that match some criteria, it is possible to code a function using the existing traversal functionality for any practical criteria. However, often either a data-driven approach is desirable, in case the criteria are not predefined and come from a file, or it is inconvenient to use traversal interfaces and a higher-level DSL is required. There is a standard language for XML processing, XPath, that can be useful for these cases. pugixml implements an almost complete subset of XPath 1.0. Because of differences in document object model and some performance implications, there are minor violations of the official specifications, which can be found in <a href="#xpath.w3c">Conformance to W3C specification</a>. The rest of this section describes the interface for XPath functionality. Please note that if you wish to learn to use XPath language, you have to look for other tutorials or manuals; for example, you can read <a href="http://www.w3schools.com/xpath/">W3Schools XPath tutorial</a>, <a href="http://www.tizag.com/xmlTutorial/xpathtutorial.php">XPath tutorial at tizag.com</a>, and <a href="http://www.w3.org/TR/xpath/">the XPath 1.0 specification</a>.</p>
</div>
<div class="sect2">
<h3 id="xpath.types"><a class="anchor" href="#xpath.types"></a>8.1. XPath types</h3>
<div class="paragraph">
<p><a id="xpath_value_type"></a><a id="xpath_type_number"></a><a id="xpath_type_string"></a><a id="xpath_type_boolean"></a><a id="xpath_type_node_set"></a><a id="xpath_type_none"></a>
Each XPath expression can have one of the following types: boolean, number, string or node set. Boolean type corresponds to <code>bool</code> type, number type corresponds to <code>double</code> type, string type corresponds to either <code>std::string</code> or <code>std::wstring</code>, depending on whether <a href="#dom.unicode">wide character interface is enabled</a>, and node set corresponds to <a href="#xpath_node_set">xpath_node_set</a> type. There is an enumeration, <code>xpath_value_type</code>, which can take the values <code>xpath_type_boolean</code>, <code>xpath_type_number</code>, <code>xpath_type_string</code> or <code>xpath_type_node_set</code>, accordingly.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node"></a><a id="xpath_node::node"></a><a id="xpath_node::attribute"></a><a id="xpath_node::parent"></a>
Because an XPath node can be either a node or an attribute, there is a special type, <code>xpath_node</code>, which is a discriminated union of these types. A value of this type contains two node handles, one of <code>xml_node</code> type, and another one of <code>xml_attribute</code> type; at most one of them can be non-null. The accessors to get these handles are available:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xml_node</span> <span class="tok-n">xpath_node</span><span class="tok-o">::</span><span class="tok-n">node</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xml_attribute</span> <span class="tok-n">xpath_node</span><span class="tok-o">::</span><span class="tok-n">attribute</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>XPath nodes can be null, in which case both accessors return null handles.</p>
</div>
<div class="paragraph">
<p>Note that as per XPath specification, each XPath node has a parent, which can be retrieved via this function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xml_node</span> <span class="tok-n">xpath_node</span><span class="tok-o">::</span><span class="tok-n">parent</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>parent</code> function returns the node’s parent if the XPath node corresponds to <code>xml_node</code> handle (equivalent to <code>node().parent()</code>), or the node to which the attribute belongs to, if the XPath node corresponds to <code>xml_attribute</code> handle. For null nodes, <code>parent</code> returns null handle.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node::unspecified_bool_type"></a><a id="xpath_node::comparison"></a>
Like node and attribute handles, XPath node handles can be implicitly cast to boolean-like object to check if it is a null node, and also can be compared for equality with each other.</p>
</div>
<div id="xpath_node::ctor" class="paragraph">
<p>You can also create XPath nodes with one of the three constructors: the default constructor, the constructor that takes node argument, and the constructor that takes attribute and node arguments (in which case the attribute must belong to the attribute list of the node). The constructor from <code>xml_node</code> is implicit, so you can usually pass <code>xml_node</code> to functions that expect <code>xpath_node</code>. Apart from that you usually don’t need to create your own XPath node objects, since they are returned to you via selection functions.</p>
</div>
<div id="xpath_node_set" class="paragraph">
<p>XPath expressions operate not on single nodes, but instead on node sets. A node set is a collection of nodes, which can be optionally ordered in either a forward document order or a reverse one. Document order is defined in XPath specification; an XPath node is before another node in document order if it appears before it in XML representation of the corresponding document.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node_set::const_iterator"></a><a id="xpath_node_set::begin"></a><a id="xpath_node_set::end"></a>
Node sets are represented by <code>xpath_node_set</code> object, which has an interface that resembles one of sequential random-access containers. It has an iterator type along with usual begin/past-the-end iterator accessors:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">typedef</span> <span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">*</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">const_iterator</span><span class="tok-p">;</span>
<span class="tok-n">const_iterator</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">begin</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">const_iterator</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">end</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><a id="xpath_node_set::index"></a><a id="xpath_node_set::size"></a><a id="xpath_node_set::empty"></a>
And it also can be iterated via indices, just like <code>std::vector</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-k">operator</span><span class="tok-p">[](</span><span class="tok-kt">size_t</span> <span class="tok-n">index</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">size_t</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">size</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">empty</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>All of the above operations have the same semantics as that of <code>std::vector</code>: the iterators are random-access, all of the above operations are constant time, and accessing the element at index that is greater or equal than the set size results in undefined behavior. You can use both iterator-based and index-based access for iteration, however the iterator-based one can be faster.</p>
</div>
<div class="paragraph">
<p><a id="xpath_node_set::type"></a><a id="xpath_node_set::type_unsorted"></a><a id="xpath_node_set::type_sorted"></a><a id="xpath_node_set::type_sorted_reverse"></a><a id="xpath_node_set::sort"></a>
The order of iteration depends on the order of nodes inside the set; the order can be queried via the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">enum</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-kt">type_t</span> <span class="tok-p">{</span><span class="tok-n">type_unsorted</span><span class="tok-p">,</span> <span class="tok-n">type_sorted</span><span class="tok-p">,</span> <span class="tok-n">type_sorted_reverse</span><span class="tok-p">};</span>
<span class="tok-kt">type_t</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">type</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>type</code> function returns the current order of nodes; <code>type_sorted</code> means that the nodes are in forward document order, <code>type_sorted_reverse</code> means that the nodes are in reverse document order, and <code>type_unsorted</code> means that neither order is guaranteed (nodes can accidentally be in a sorted order even if <code>type()</code> returns <code>type_unsorted</code>). If you require a specific order of iteration, you can change it via <code>sort</code> function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">void</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">sort</span><span class="tok-p">(</span><span class="tok-kt">bool</span> <span class="tok-n">reverse</span> <span class="tok-o">=</span> <span class="tok-nb">false</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Calling <code>sort</code> sorts the nodes in either forward or reverse document order, depending on the argument; after this call <code>type()</code> will return <code>type_sorted</code> or <code>type_sorted_reverse</code>.</p>
</div>
<div id="xpath_node_set::first" class="paragraph">
<p>Often the actual iteration is not needed; instead, only the first element in document order is required. For this, a special accessor is provided:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_node</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">first</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This function returns the first node in forward document order from the set, or null node if the set is empty. Note that while the result of the node does not depend on the order of nodes in the set (i.e. on the result of <code>type()</code>), the complexity does - if the set is sorted, the complexity is constant, otherwise it is linear in the number of elements or worse.</p>
</div>
<div id="xpath_node_set::ctor" class="paragraph">
<p>While in the majority of cases the node set is returned by XPath functions, sometimes there is a need to manually construct a node set. For such cases, a constructor is provided which takes an iterator range (<code>const_iterator</code> is a typedef for <code>const xpath_node*</code>), and an optional type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-p">(</span><span class="tok-n">const_iterator</span> <span class="tok-n">begin</span><span class="tok-p">,</span> <span class="tok-n">const_iterator</span> <span class="tok-n">end</span><span class="tok-p">,</span> <span class="tok-kt">type_t</span> <span class="tok-n">type</span> <span class="tok-o">=</span> <span class="tok-n">type_unsorted</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The constructor copies the specified range and sets the specified type. The objects in the range are not checked in any way; you’ll have to ensure that the range contains no duplicates, and that the objects are sorted according to the <code>type</code> parameter. Otherwise XPath operations with this set may produce unexpected results.</p>
</div>
</div>
<div class="sect2">
<h3 id="xpath.select"><a class="anchor" href="#xpath.select"></a>8.2. Selecting nodes via XPath expression</h3>
<div class="paragraph">
<p><a id="xml_node::select_node"></a><a id="xml_node::select_nodes"></a>
If you want to select nodes that match some XPath expression, you can do it with the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>select_nodes</code> function compiles the expression and then executes it with the node as a context node, and returns the resulting node set. <code>select_node</code> returns only the first node in document order from the result, and is equivalent to calling <code>select_nodes(query).first()</code>. If the XPath expression does not match anything, or the node handle is null, <code>select_nodes</code> returns an empty set, and <code>select_node</code> returns null XPath node.</p>
</div>
<div class="paragraph">
<p>If exception handling is not disabled, both functions throw <a href="#xpath_exception">xpath_exception</a> if the query can not be compiled or if it returns a value with type other than node set; see <a href="#xpath.errors">Error handling</a> for details.</p>
</div>
<div class="paragraph">
<p><a id="xml_node::select_node_precomp"></a><a id="xml_node::select_nodes_precomp"></a>
While compiling expressions is fast, the compilation time can introduce a significant overhead if the same expression is used many times on small subtrees. If you’re doing many similar queries, consider compiling them into query objects (see <a href="#xpath.query">Using query objects</a> for further reference). Once you get a compiled query object, you can pass it to select functions instead of an expression string:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_query</span><span class="tok-o">&</span> <span class="tok-n">query</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_query</span><span class="tok-o">&</span> <span class="tok-n">query</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If exception handling is not disabled, both functions throw <a href="#xpath_exception">xpath_exception</a> if the query returns a value with type other than node set.</p>
</div>
<div class="paragraph">
<p>This is an example of selecting nodes using XPath expressions (<a href="samples/xpath_select.cpp" class="bare">samples/xpath_select.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">"/Profile/Tools/Tool[@AllowRemote='true' and @DeriveCaptionFrom='lastparam']"</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Tools:</span><span class="tok-se">\n</span><span class="tok-s">"</span><span class="tok-p">;</span>
<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span><span class="tok-o">::</span><span class="tok-n">const_iterator</span> <span class="tok-n">it</span> <span class="tok-o">=</span> <span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">begin</span><span class="tok-p">();</span> <span class="tok-n">it</span> <span class="tok-o">!=</span> <span class="tok-n">tools</span><span class="tok-p">.</span><span class="tok-n">end</span><span class="tok-p">();</span> <span class="tok-o">++</span><span class="tok-n">it</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span> <span class="tok-n">node</span> <span class="tok-o">=</span> <span class="tok-o">*</span><span class="tok-n">it</span><span class="tok-p">;</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">node</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">"Filename"</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span> <span class="tok-o"><<</span> <span class="tok-s">"</span><span class="tok-se">\n</span><span class="tok-s">"</span><span class="tok-p">;</span>
<span class="tok-p">}</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node</span> <span class="tok-n">build_tool</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-s">"//Tool[contains(Description, 'build system')]"</span><span class="tok-p">);</span>
<span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-n">build_tool</span><span class="tok-p">)</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Build tool: "</span> <span class="tok-o"><<</span> <span class="tok-n">build_tool</span><span class="tok-p">.</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">attribute</span><span class="tok-p">(</span><span class="tok-s">"Filename"</span><span class="tok-p">).</span><span class="tok-n">value</span><span class="tok-p">()</span> <span class="tok-o"><<</span> <span class="tok-s">"</span><span class="tok-se">\n</span><span class="tok-s">"</span><span class="tok-p">;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.query"><a class="anchor" href="#xpath.query"></a>8.3. Using query objects</h3>
<div id="xpath_query" class="paragraph">
<p>When you call <code>select_nodes</code> with an expression string as an argument, a query object is created behind the scenes. A query object represents a compiled XPath expression. Query objects can be needed in the following circumstances:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>You can precompile expressions to query objects to save compilation time if it becomes an issue;</p>
</li>
<li>
<p>You can use query objects to evaluate XPath expressions which result in booleans, numbers or strings;</p>
</li>
<li>
<p>You can get the type of expression value via query object.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Query objects correspond to <code>xpath_query</code> type. They are immutable and non-copyable: they are bound to the expression at creation time and can not be cloned. If you want to put query objects in a container, allocate them on heap via <code>new</code> operator and store pointers to <code>xpath_query</code> in the container.</p>
</div>
<div id="xpath_query::ctor" class="paragraph">
<p>You can create a query object with the constructor that takes XPath expression as an argument:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">explicit</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div id="xpath_query::return_type" class="paragraph">
<p>The expression is compiled and the compiled representation is stored in the new query object. If compilation fails, <a href="#xpath_exception">xpath_exception</a> is thrown if exception handling is not disabled (see <a href="#xpath.errors">Error handling</a> for details). After the query is created, you can query the type of the evaluation result using the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_value_type</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">return_type</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><a id="xpath_query::evaluate_boolean"></a><a id="xpath_query::evaluate_number"></a><a id="xpath_query::evaluate_string"></a><a id="xpath_query::evaluate_node_set"></a><a id="xpath_query::evaluate_node"></a>
You can evaluate the query using one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_boolean</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">double</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_number</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">string_t</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_string</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>All functions take the context node as an argument, compute the expression and return the result, converted to the requested type. According to XPath specification, value of any type can be converted to boolean, number or string value, but no type other than node set can be converted to node set. Because of this, <code>evaluate_boolean</code>, <code>evaluate_number</code> and <code>evaluate_string</code> always return a result, but <code>evaluate_node_set</code> and <code>evaluate_node</code> result in an error if the return type is not node set (see <a href="#xpath.errors">Error handling</a>).</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
Calling <code>node.select_nodes("query")</code> is equivalent to calling <code>xpath_query("query").evaluate_node_set(node)</code>. Calling <code>node.select_node("query")</code> is equivalent to calling <code>xpath_query("query").evaluate_node(node)</code>.
</td>
</tr>
</table>
</div>
<div id="xpath_query::evaluate_string_buffer" class="paragraph">
<p>Note that <code>evaluate_string</code> function returns the STL string; as such, it’s not available in <a href="#PUGIXML_NO_STL">PUGIXML_NO_STL</a> mode and also usually allocates memory. There is another string evaluation function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">size_t</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">evaluate_string</span><span class="tok-p">(</span><span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">buffer</span><span class="tok-p">,</span> <span class="tok-kt">size_t</span> <span class="tok-n">capacity</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xpath_node</span><span class="tok-o">&</span> <span class="tok-n">n</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This function evaluates the string, and then writes the result to <code>buffer</code> (but at most <code>capacity</code> characters); then it returns the full size of the result in characters, including the terminating zero. If <code>capacity</code> is not 0, the resulting buffer is always zero-terminated. You can use this function as follows:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>First call the function with <code>buffer = 0</code> and <code>capacity = 0</code>; then allocate the returned amount of characters, and call the function again, passing the allocated storage and the amount of characters;</p>
</li>
<li>
<p>First call the function with small buffer and buffer capacity; then, if the result is larger than the capacity, the output has been trimmed, so allocate a larger buffer and call the function again.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This is an example of using query objects (<a href="samples/xpath_query.cpp" class="bare">samples/xpath_query.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// Select nodes via compiled query</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">(</span><span class="tok-s">"/Profile/Tools/Tool[@AllowRemote='true']"</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools</span> <span class="tok-o">=</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">.</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Remote tool: "</span><span class="tok-p">;</span>
<span class="tok-n">tools</span><span class="tok-p">[</span><span class="tok-mi">2</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-c1">// Evaluate numbers via compiled query</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_timeouts</span><span class="tok-p">(</span><span class="tok-s">"sum(//Tool/@Timeout)"</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">query_timeouts</span><span class="tok-p">.</span><span class="tok-n">evaluate_number</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">)</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-c1">// Evaluate strings via compiled query for different context nodes</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_name_valid</span><span class="tok-p">(</span><span class="tok-s">"string-length(substring-before(@Filename, '_')) > 0 and @OutputFileMasks"</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_name</span><span class="tok-p">(</span><span class="tok-s">"concat(substring-before(@Filename, '_'), ' produces ', @OutputFileMasks)"</span><span class="tok-p">);</span>
<span class="tok-k">for</span> <span class="tok-p">(</span><span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xml_node</span> <span class="tok-n">tool</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">first_element_by_path</span><span class="tok-p">(</span><span class="tok-s">"Profile/Tools/Tool"</span><span class="tok-p">);</span> <span class="tok-n">tool</span><span class="tok-p">;</span> <span class="tok-n">tool</span> <span class="tok-o">=</span> <span class="tok-n">tool</span><span class="tok-p">.</span><span class="tok-n">next_sibling</span><span class="tok-p">())</span>
<span class="tok-p">{</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">string</span> <span class="tok-n">s</span> <span class="tok-o">=</span> <span class="tok-n">query_name</span><span class="tok-p">.</span><span class="tok-n">evaluate_string</span><span class="tok-p">(</span><span class="tok-n">tool</span><span class="tok-p">);</span>
<span class="tok-k">if</span> <span class="tok-p">(</span><span class="tok-n">query_name_valid</span><span class="tok-p">.</span><span class="tok-n">evaluate_boolean</span><span class="tok-p">(</span><span class="tok-n">tool</span><span class="tok-p">))</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-n">s</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.variables"><a class="anchor" href="#xpath.variables"></a>8.4. Using variables</h3>
<div class="paragraph">
<p>XPath queries may contain references to variables; this is useful if you want to use queries that depend on some dynamic parameter without manually preparing the complete query string, or if you want to reuse the same query object for similar queries.</p>
</div>
<div class="paragraph">
<p>Variable references have the form <code>$name</code>; in order to use them, you have to provide a variable set, which includes all variables present in the query with correct types. This set is passed to <code>xpath_query</code> constructor or to <code>select_nodes</code>/<code>select_node</code> functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">explicit</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">);</span>
<span class="tok-n">xpath_node</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_node</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_node_set</span> <span class="tok-n">xml_node</span><span class="tok-o">::</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">query</span><span class="tok-p">,</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">*</span> <span class="tok-n">variables</span> <span class="tok-o">=</span> <span class="tok-mi">0</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If you’re using query objects, you can change the variable values before <code>evaluate</code>/<code>select</code> calls to change the query behavior.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The variable set pointer is stored in the query object; you have to ensure that the lifetime of the set exceeds that of query object.
</td>
</tr>
</table>
</div>
<div id="xpath_variable_set" class="paragraph">
<p>Variable sets correspond to <code>xpath_variable_set</code> type, which is essentially a variable container.</p>
</div>
<div id="xpath_variable_set::add" class="paragraph">
<p>You can add new variables with the following function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_variable</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">add</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-n">xpath_value_type</span> <span class="tok-n">type</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The function tries to add a new variable with the specified name and type; if the variable with such name does not exist in the set, the function adds a new variable and returns the variable handle; if there is already a variable with the specified name, the function returns the variable handle if variable has the specified type. Otherwise the function returns null pointer; it also returns null pointer on allocation failure.</p>
</div>
<div class="paragraph">
<p>New variables are assigned the default value which depends on the type: <code>0</code> for numbers, <code>false</code> for booleans, empty string for strings and empty set for node sets.</p>
</div>
<div id="xpath_variable_set::get" class="paragraph">
<p>You can get the existing variables with the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-n">xpath_variable</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">get</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">);</span>
<span class="tok-k">const</span> <span class="tok-n">xpath_variable</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">get</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">)</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The functions return the variable handle, or null pointer if the variable with the specified name is not found.</p>
</div>
<div id="xpath_variable_set::set" class="paragraph">
<p>Additionally, there are the helper functions for setting the variable value by name; they try to add the variable with the corresponding type, if it does not exist, and to set the value. If the variable with the same name but with different type is already present, they return <code>false</code>; they also return <code>false</code> on allocation failure. Note that these functions do not perform any type conversions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-kt">bool</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-kt">double</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable_set</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">name</span><span class="tok-p">,</span> <span class="tok-k">const</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">&</span> <span class="tok-n">value</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The variable values are copied to the internal variable storage, so you can modify or destroy them after the functions return.</p>
</div>
<div id="xpath_variable" class="paragraph">
<p>If setting variables by name is not efficient enough, or if you have to inspect variable information or get variable values, you can use variable handles. A variable corresponds to the <code>xpath_variable</code> type, and a variable handle is simply a pointer to <code>xpath_variable</code>.</p>
</div>
<div class="paragraph">
<p><a id="xpath_variable::type"></a><a id="xpath_variable::name"></a>
In order to get variable information, you can use one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">name</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-n">xpath_value_type</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">type</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that each variable has a distinct type which is specified upon variable creation and can not be changed later.</p>
</div>
<div class="paragraph">
<p><a id="xpath_variable::get_boolean"></a><a id="xpath_variable::get_number"></a><a id="xpath_variable::get_string"></a><a id="xpath_variable::get_node_set"></a>
In order to get variable value, you should use one of the following functions, depending on the variable type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_boolean</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-kt">double</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_number</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_string</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-k">const</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">&</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">get_node_set</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions return the value of the variable. Note that no type conversions are performed; if the type mismatch occurs, a dummy value is returned (<code>false</code> for booleans, <code>NaN</code> for numbers, empty string for strings and empty set for node sets).</p>
</div>
<div id="xpath_variable::set" class="paragraph">
<p>In order to set variable value, you should use one of the following functions, depending on the variable type:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-kt">bool</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-kt">double</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-kt">char_t</span><span class="tok-o">*</span> <span class="tok-n">value</span><span class="tok-p">);</span>
<span class="tok-kt">bool</span> <span class="tok-n">xpath_variable</span><span class="tok-o">::</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">xpath_node_set</span><span class="tok-o">&</span> <span class="tok-n">value</span><span class="tok-p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>These functions modify the variable value. Note that no type conversions are performed; if the type mismatch occurs, the functions return <code>false</code>; they also return <code>false</code> on allocation failure. The variable values are copied to the internal variable storage, so you can modify or destroy them after the functions return.</p>
</div>
<div class="paragraph">
<p>This is an example of using variables in XPath queries (<a href="samples/xpath_variables.cpp" class="bare">samples/xpath_variables.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// Select nodes via compiled query</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_variable_set</span> <span class="tok-n">vars</span><span class="tok-p">;</span>
<span class="tok-n">vars</span><span class="tok-p">.</span><span class="tok-n">add</span><span class="tok-p">(</span><span class="tok-s">"remote"</span><span class="tok-p">,</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_type_boolean</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_query</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">(</span><span class="tok-s">"/Profile/Tools/Tool[@AllowRemote = string($remote)]"</span><span class="tok-p">,</span> <span class="tok-o">&</span><span class="tok-n">vars</span><span class="tok-p">);</span>
<span class="tok-n">vars</span><span class="tok-p">.</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-s">"remote"</span><span class="tok-p">,</span> <span class="tok-nb">true</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools_remote</span> <span class="tok-o">=</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">.</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">);</span>
<span class="tok-n">vars</span><span class="tok-p">.</span><span class="tok-n">set</span><span class="tok-p">(</span><span class="tok-s">"remote"</span><span class="tok-p">,</span> <span class="tok-nb">false</span><span class="tok-p">);</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools_local</span> <span class="tok-o">=</span> <span class="tok-n">query_remote_tools</span><span class="tok-p">.</span><span class="tok-n">evaluate_node_set</span><span class="tok-p">(</span><span class="tok-n">doc</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Remote tool: "</span><span class="tok-p">;</span>
<span class="tok-n">tools_remote</span><span class="tok-p">[</span><span class="tok-mi">2</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Local tool: "</span><span class="tok-p">;</span>
<span class="tok-n">tools_local</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span>
<span class="tok-c1">// You can pass the context directly to select_nodes/select_node</span>
<span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_node_set</span> <span class="tok-n">tools_local_imm</span> <span class="tok-o">=</span> <span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">"/Profile/Tools/Tool[@AllowRemote = string($remote)]"</span><span class="tok-p">,</span> <span class="tok-o">&</span><span class="tok-n">vars</span><span class="tok-p">);</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Local tool imm: "</span><span class="tok-p">;</span>
<span class="tok-n">tools_local_imm</span><span class="tok-p">[</span><span class="tok-mi">0</span><span class="tok-p">].</span><span class="tok-n">node</span><span class="tok-p">().</span><span class="tok-n">print</span><span class="tok-p">(</span><span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span><span class="tok-p">);</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.errors"><a class="anchor" href="#xpath.errors"></a>8.5. Error handling</h3>
<div class="paragraph">
<p>There are two different mechanisms for error handling in XPath implementation; the mechanism used depends on whether exception support is disabled (this is controlled with <a href="#PUGIXML_NO_EXCEPTIONS">PUGIXML_NO_EXCEPTIONS</a> define).</p>
</div>
<div class="paragraph">
<p><a id="xpath_exception"></a><a id="xpath_exception::result"></a><a id="xpath_exception::what"></a>
By default, XPath functions throw <code>xpath_exception</code> object in case of errors; additionally, in the event any memory allocation fails, an <code>std::bad_alloc</code> exception is thrown. Also <code>xpath_exception</code> is thrown if the query is evaluated to a node set, but the return type is not node set. If the query constructor succeeds (i.e. no exception is thrown), the query object is valid. Otherwise you can get the error details via one of the following functions:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">virtual</span> <span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">xpath_exception</span><span class="tok-o">::</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-k">const</span> <span class="tok-k">throw</span><span class="tok-p">();</span>
<span class="tok-k">const</span> <span class="tok-n">xpath_parse_result</span><span class="tok-o">&</span> <span class="tok-n">xpath_exception</span><span class="tok-o">::</span><span class="tok-n">result</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><a id="xpath_query::unspecified_bool_type"></a><a id="xpath_query::result"></a>
If exceptions are disabled, then in the event of parsing failure the query is initialized to invalid state; you can test if the query object is valid by using it in a boolean expression: <code>if (query) { …​ }</code>. Additionally, you can get parsing result via the result() accessor:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">const</span> <span class="tok-n">xpath_parse_result</span><span class="tok-o">&</span> <span class="tok-n">xpath_query</span><span class="tok-o">::</span><span class="tok-n">result</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Without exceptions, evaluating invalid query results in <code>false</code>, empty string, <code>NaN</code> or an empty node set, depending on the type; evaluating a query as a node set results in an empty node set if the return type is not node set.</p>
</div>
<div id="xpath_parse_result" class="paragraph">
<p>The information about parsing result is returned via <code>xpath_parse_result</code> object. It contains parsing status and the offset of last successfully parsed character from the beginning of the source stream:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-k">struct</span> <span class="tok-n">xpath_parse_result</span>
<span class="tok-p">{</span>
<span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">error</span><span class="tok-p">;</span>
<span class="tok-kt">ptrdiff_t</span> <span class="tok-n">offset</span><span class="tok-p">;</span>
<span class="tok-k">operator</span> <span class="tok-kt">bool</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-k">const</span> <span class="tok-kt">char</span><span class="tok-o">*</span> <span class="tok-n">description</span><span class="tok-p">()</span> <span class="tok-k">const</span><span class="tok-p">;</span>
<span class="tok-p">};</span></code></pre>
</div>
</div>
<div id="xpath_parse_result::error" class="paragraph">
<p>Parsing result is represented as the error message; it is either a null pointer, in case there is no error, or the error message in the form of ASCII zero-terminated string.</p>
</div>
<div id="xpath_parse_result::description" class="paragraph">
<p><code>description()</code> member function can be used to get the error message; it never returns the null pointer, so you can safely use <code>description()</code> even if query parsing succeeded. Note that <code>description()</code> returns a <code>char</code> string even in <code>PUGIXML_WCHAR_MODE</code>; you’ll have to call <a href="#as_wide">as_wide</a> to get the <code>wchar_t</code> string.</p>
</div>
<div id="xpath_parse_result::offset" class="paragraph">
<p>In addition to the error message, parsing result has an <code>offset</code> member, which contains the offset of last successfully parsed character. This offset is in units of <a href="#char_t">pugi::char_t</a> (bytes for character mode, wide characters for wide character mode).</p>
</div>
<div id="xpath_parse_result::bool" class="paragraph">
<p>Parsing result object can be implicitly converted to <code>bool</code> like this: <code>if (result) { …​ } else { …​ }</code>.</p>
</div>
<div class="paragraph">
<p>This is an example of XPath error handling (<a href="samples/xpath_error.cpp" class="bare">samples/xpath_error.cpp</a>):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="c++"><span class="tok-c1">// Exception is thrown for incorrect query syntax</span>
<span class="tok-n">try</span>
<span class="tok-p">{</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">"//nodes[#true()]"</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-k">catch</span> <span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_exception</span><span class="tok-o">&</span> <span class="tok-n">e</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Select failed: "</span> <span class="tok-o"><<</span> <span class="tok-n">e</span><span class="tok-p">.</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span>
<span class="tok-c1">// Exception is thrown for incorrect query semantics</span>
<span class="tok-n">try</span>
<span class="tok-p">{</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">"(123)/next"</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-k">catch</span> <span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_exception</span><span class="tok-o">&</span> <span class="tok-n">e</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Select failed: "</span> <span class="tok-o"><<</span> <span class="tok-n">e</span><span class="tok-p">.</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span>
<span class="tok-c1">// Exception is thrown for query with incorrect return type</span>
<span class="tok-n">try</span>
<span class="tok-p">{</span>
<span class="tok-n">doc</span><span class="tok-p">.</span><span class="tok-n">select_nodes</span><span class="tok-p">(</span><span class="tok-s">"123"</span><span class="tok-p">);</span>
<span class="tok-p">}</span>
<span class="tok-k">catch</span> <span class="tok-p">(</span><span class="tok-k">const</span> <span class="tok-n">pugi</span><span class="tok-o">::</span><span class="tok-n">xpath_exception</span><span class="tok-o">&</span> <span class="tok-n">e</span><span class="tok-p">)</span>
<span class="tok-p">{</span>
<span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">cout</span> <span class="tok-o"><<</span> <span class="tok-s">"Select failed: "</span> <span class="tok-o"><<</span> <span class="tok-n">e</span><span class="tok-p">.</span><span class="tok-n">what</span><span class="tok-p">()</span> <span class="tok-o"><<</span> <span class="tok-n">std</span><span class="tok-o">::</span><span class="tok-n">endl</span><span class="tok-p">;</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xpath.w3c"><a class="anchor" href="#xpath.w3c"></a>8.6. Conformance to W3C specification</h3>
<div class="paragraph">
<p>Because of the differences in document object models, performance considerations and implementation complexity, pugixml does not provide a fully conformant XPath 1.0 implementation. This is the current list of incompatibilities:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Consecutive text nodes sharing the same parent are not merged, i.e. in <code><node>text1 <![CDATA[data]]> text2</node></code> node should have one text node child, but instead has three.</p>
</li>
<li>
<p>Since the document type declaration is not used for parsing, <code>id()</code> function always returns an empty node set.</p>
</li>
<li>
<p>Namespace nodes are not supported (affects <code>namespace::</code> axis).</p>
</li>
<li>
<p>Name tests are performed on QNames in XML document instead of expanded names; for <code><foo xmlns:ns1='uri' xmlns:ns2='uri'><ns1:child/><ns2:child/></foo></code>, query <code>foo/ns1:*</code> will return only the first child, not both of them. Compliant XPath implementations can return both nodes if the user provides appropriate namespace declarations.</p>
</li>
<li>
<p>String functions consider a character to be either a single <code>char</code> value or a single <code>wchar_t</code> value, depending on the library configuration; this means that some string functions are not fully Unicode-aware. This affects <code>substring()</code>, <code>string-length()</code> and <code>translate()</code> functions.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">