• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

xmlunit / xmlunit / 933c4914-1b6b-480a-ba31-f8dc032776b8

31 May 2026 08:54AM UTC coverage: 91.787%. Remained the same
933c4914-1b6b-480a-ba31-f8dc032776b8

push

circleci

web-flow
Merge pull request #328 from xmlunit/fix-tests-introduce-new-DefaultWithDtdParsing-configuration

introduce DefaultWithDTDParsing configuration

4026 of 4738 branches covered (84.97%)

5 of 5 new or added lines in 1 file covered. (100.0%)

5 existing lines in 1 file now uncovered.

11802 of 12858 relevant lines covered (91.79%)

2.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.03
/xmlunit-core/src/main/java/org/xmlunit/util/DocumentBuilderFactoryConfigurer.java
1
/*
2
  This file is licensed to You under the Apache License, Version 2.0
3
  (the "License"); you may not use this file except in compliance with
4
  the License.  You may obtain a copy of the License at
5

6
  http://www.apache.org/licenses/LICENSE-2.0
7

8
  Unless required by applicable law or agreed to in writing, software
9
  distributed under the License is distributed on an "AS IS" BASIS,
10
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
  See the License for the specific language governing permissions and
12
  limitations under the License.
13
*/
14
package org.xmlunit.util;
15

16
import java.util.Arrays;
17
import java.util.Collections;
18
import java.util.HashMap;
19
import java.util.List;
20
import java.util.Map;
21
import javax.xml.parsers.DocumentBuilderFactory;
22
import javax.xml.parsers.ParserConfigurationException;
23

24
import org.xmlunit.ConfigurationException;
25

26
/**
27
 * Configures DocumentBuilderFactories.
28
 *
29
 * @since XMLUnit 2.6.0
30
 */
31
public class DocumentBuilderFactoryConfigurer {
32

33
    private final Map<String, Object> attributes, safeAttributes;
34
    private final Map<String, Boolean> features, safeFeatures;
35
    private final boolean xIncludeAware, expandEntityRefs;
36

37
    private DocumentBuilderFactoryConfigurer(Map<String, Object> attributes, Map<String, Object> safeAttributes,
38
            Map<String, Boolean> features, Map<String, Boolean> safeFeatures, boolean xIncludeAware,
39
            boolean expandEntityRefs) {
1✔
40
        this.attributes = attributes;
1✔
41
        this.safeAttributes = safeAttributes;
1✔
42
        this.features = features;
1✔
43
        this.safeFeatures = safeFeatures;
1✔
44
        this.xIncludeAware = xIncludeAware;
1✔
45
        this.expandEntityRefs = expandEntityRefs;
1✔
46
    }
1✔
47

48
    /**
49
     * Applies the current configuration.
50
     *
51
     * @param factory the factory to configure
52
     * @return the configured factory
53
     * @throws ConfigurationException if any of the attributes or
54
     * features set is not supported.
55
     */
56
    public DocumentBuilderFactory configure(DocumentBuilderFactory factory) {
57
        for (Map.Entry<String, Object> attr : attributes.entrySet()) {
1!
58
            try {
59
                factory.setAttribute(attr.getKey(), attr.getValue());
×
60
            } catch (IllegalArgumentException ex) {
×
61
                throw new ConfigurationException("Error setting attribute " + attr.getKey(), ex);
×
62
            }
×
63
        }
×
64
        for (Map.Entry<String, Object> attr : safeAttributes.entrySet()) {
1!
65
            try {
66
                factory.setAttribute(attr.getKey(), attr.getValue());
×
67
            } catch (IllegalArgumentException ex) {
×
68
                // swallow
69
            }
×
70
        }
×
71
        for (Map.Entry<String, Boolean> feat : features.entrySet()) {
1!
72
            try {
73
                factory.setFeature(feat.getKey(), feat.getValue());
×
74
            } catch (ParserConfigurationException ex) {
×
75
                throw new ConfigurationException("Error setting feature " + feat.getKey(), ex);
×
76
            }
×
77
        }
×
78
        for (Map.Entry<String, Boolean> feat : safeFeatures.entrySet()) {
1✔
79
            try {
80
                factory.setFeature(feat.getKey(), feat.getValue());
1✔
81
            } catch (ParserConfigurationException ex) {
1✔
82
                // swallow
83
            }
1✔
84
        }
1✔
85
        factory.setXIncludeAware(xIncludeAware);
1✔
86
        factory.setExpandEntityReferences(expandEntityRefs);
1✔
87
        return factory;
1✔
88
    }
89

90
    /**
91
     * Creates a builder for DocumentBuilderFactoryConfigurers.
92
     * @return a new builder
93
     */
94
    public static Builder builder() {
95
        return new Builder();
1✔
96
    }
97

98
    /**
99
     * The default instance.
100
     */
101
    public static final DocumentBuilderFactoryConfigurer Default = builder()
1✔
102
        .withDTDParsingDisabled()
1✔
103
        .withDTDLoadingDisabled()
1✔
104
        .withXIncludeAware(false)
1✔
105
        .withExpandEntityReferences(false)
1✔
106
        .build();
1✔
107

108
    /**
109
     * A relaxed instance that allows DTD parsing but prohibits loading of external entities.
110
     *
111
     * @since XMLUnit 2.12.0
112
     */
113
    public static final DocumentBuilderFactoryConfigurer DefaultWithDTDParsing = builder()
1✔
114
        .withDTDLoadingDisabled()
1✔
115
        .withXIncludeAware(false)
1✔
116
        .withExpandEntityReferences(false)
1✔
117
        .build();
1✔
118

119
    /**
120
     * Builder for a DocumentBuilderFactoryConfigurer.
121
     *
122
     * @since XMLUnit 2.6.0
123
     */
124
    public static class Builder {
1✔
125
        private final Map<String, Object> attributes = new HashMap<String, Object>();
1✔
126
        private final Map<String, Object> safeAttributes = new HashMap<String, Object>();
1✔
127
        private final Map<String, Boolean> features = new HashMap<String, Boolean>();
1✔
128
        private final Map<String, Boolean> safeFeatures = new HashMap<String, Boolean>();
1✔
129
        private boolean xIncludeAware = false;
1✔
130
        private boolean expandEntityRefs = false;
1✔
131

132
        /**
133
         * Builds a DocumentBuilderFactoryConfigurer.
134
         * @return the built configurer
135
         */
136
        public DocumentBuilderFactoryConfigurer build() {
137
            return new DocumentBuilderFactoryConfigurer(Collections.unmodifiableMap(attributes),
1✔
138
                Collections.unmodifiableMap(safeAttributes), Collections.unmodifiableMap(features),
1✔
139
                Collections.unmodifiableMap(safeFeatures), xIncludeAware, expandEntityRefs);
1✔
140
        }
141

142
        /**
143
         * Configures the factory with the given attribute, causes an
144
         * exception in {@link #configure} if the attribute is not
145
         * supported.
146
         * @param key key of the attribute
147
         * @param value value for the attribute
148
         * @return this
149
         */
150
        public Builder withAttribute(String key, Object value) {
UNCOV
151
            attributes.put(key, value);
×
UNCOV
152
            return this;
×
153
        }
154

155
        /**
156
         * Configures the factory with the given attribute if it is
157
         * supported.
158
         * @param key key of the attribute
159
         * @param value value for the attribute
160
         * @return this
161
         */
162
        public Builder withSafeAttribute(String key, Object value) {
163
            safeAttributes.put(key, value);
×
UNCOV
164
            return this;
×
165
        }
166

167
        /**
168
         * Configures the factory with the given feature, causes an
169
         * exception in {@link #configure} if the feature is not
170
         * supported.
171
         * @param key key of the feature
172
         * @param value value for the feature
173
         * @return this
174
         */
175
        public Builder withFeature(String key, boolean value) {
UNCOV
176
            features.put(key, value);
×
UNCOV
177
            return this;
×
178
        }
179

180
        /**
181
         * Configures the factory with the given feature if it is
182
         * supported.
183
         * @param key key of the feature
184
         * @param value value for the feature
185
         * @return this
186
         */
187
        public Builder withSafeFeature(String key, boolean value) {
188
            safeFeatures.put(key, value);
1✔
189
            return this;
1✔
190
        }
191

192
        private static final List<String> DTD_LOAD_DISABLERS = Arrays.asList(
1✔
193
            "http://xerces.apache.org/xerces-j/features.html#external-general-entities",
194
            "http://xerces.apache.org/xerces2-j/features.html#external-general-entities",
195
            "http://xml.org/sax/features/external-general-entities",
196
            "http://apache.org/xml/features/nonvalidating/load-dtd-grammar",
197
            "http://apache.org/xml/features/nonvalidating/load-external-dtd",
198
            "http://xerces.apache.org/xerces-j/features.html#external-parameter-entities",
199
            "http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities",
200
            "http://xml.org/sax/features/external-parameter-entities"
201
        );
202

203
        /**
204
         * Configures the factory to not load any external DTDs.
205
         * @return this
206
         */
207
        public Builder withDTDLoadingDisabled() {
208
            for (String feature : DTD_LOAD_DISABLERS) {
1✔
209
                withSafeFeature(feature, false);
1✔
210
            }
1✔
211
            return this;
1✔
212
        }
213

214
        private static final List<String> DTD_PARSE_DISABLERS = Arrays.asList(
1✔
215
            "http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl",
216
            "http://apache.org/xml/features/disallow-doctype-decl"
217
        );
218

219
        /**
220
         * Configures the factory to not parse any DTDs.
221
         * @return this
222
         */
223
        public Builder withDTDParsingDisabled() {
224
            for (String feature : DTD_PARSE_DISABLERS) {
1✔
225
                withSafeFeature(feature, true);
1✔
226
            }
1✔
227
            return this;
1✔
228
        }
229

230
        /**
231
         * Configure the factory's XInclude awareness.
232
         * @param b whether the factory should be XInclude aware
233
         * @return this
234
         */
235
        public Builder withXIncludeAware(boolean b) {
236
            xIncludeAware = b;
1✔
237
            return this;
1✔
238
        }
239

240
        /**
241
         * Configure whether the factory's expands entity references.
242
         * @param b whether the factory should expand entity references
243
         * @return this
244
         */
245
        public Builder withExpandEntityReferences(boolean b) {
246
            expandEntityRefs = b;
1✔
247
            return this;
1✔
248
        }
249
    }
250
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc