22 * Provides classes and predicates for working with XML files and their content.
33 */
44
5- import semmle.code.csharp.Element
6- import semmle.code.csharp.Location
5+ import semmle.files.FileSystem
76
87/** An XML element that has a location. */
9- class XMLLocatable extends @xmllocatable {
10- XMLLocatable ( ) {
11- not this instanceof File // in the dbscheme
12- }
13-
8+ abstract class XMLLocatable extends @xmllocatable {
149 /** Gets the source location for this element. */
15- Location getALocation ( ) { xmllocations ( this , result ) }
10+ Location getLocation ( ) { xmllocations ( this , result ) }
1611
1712 /**
18- * Whether this element has the specified location information,
19- * including file path, start line, start column, end line and end column.
13+ * Holds if this element is at the specified location.
14+ * The location spans column `startcolumn` of line `startline` to
15+ * column `endcolumn` of line `endline` in file `filepath`.
16+ * For more information, see
17+ * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
2018 */
2119 predicate hasLocationInfo (
2220 string filepath , int startline , int startcolumn , int endline , int endcolumn
2321 ) {
24- exists ( File f , Location l | l = this .getALocation ( ) |
22+ exists ( File f , Location l | l = this .getLocation ( ) |
2523 locations_default ( l , f , startline , startcolumn , endline , endcolumn ) and
2624 filepath = f .getAbsolutePath ( )
2725 )
2826 }
2927
30- /** Gets a printable representation of this element. */
28+ /** Gets a textual representation of this element. */
3129 abstract string toString ( ) ;
3230}
3331
@@ -36,6 +34,12 @@ class XMLLocatable extends @xmllocatable {
3634 * both of which can contain other elements.
3735 */
3836class XMLParent extends @xmlparent {
37+ XMLParent ( ) {
38+ // explicitly restrict `this` to be either an `XMLElement` or an `XMLFile`;
39+ // the type `@xmlparent` currently also includes non-XML files
40+ this instanceof @xmlelement or xmlEncoding ( this , _)
41+ }
42+
3943 /**
4044 * Gets a printable representation of this XML parent.
4145 * (Intended to be overridden in subclasses.)
@@ -69,7 +73,25 @@ class XMLParent extends @xmlparent {
6973 /** Gets the number of places in the body of this XML parent where text occurs. */
7074 int getNumberOfCharacterSets ( ) { result = count ( int pos | xmlChars ( _, _, this , pos , _, _) ) }
7175
72- /** Append all the character sequences of this XML parent from left to right, separated by a space. */
76+ /**
77+ * DEPRECATED: Internal.
78+ *
79+ * Append the character sequences of this XML parent from left to right, separated by a space,
80+ * up to a specified (zero-based) index.
81+ */
82+ deprecated string charsSetUpTo ( int n ) {
83+ n = 0 and xmlChars ( _, result , this , 0 , _, _)
84+ or
85+ n > 0 and
86+ exists ( string chars | xmlChars ( _, chars , this , n , _, _) |
87+ result = this .charsSetUpTo ( n - 1 ) + " " + chars
88+ )
89+ }
90+
91+ /**
92+ * Gets the result of appending all the character sequences of this XML parent from
93+ * left to right, separated by a space.
94+ */
7395 string allCharactersString ( ) {
7496 result = concat ( string chars , int pos |
7597 xmlChars ( _, chars , this , pos , _, _)
@@ -93,15 +115,21 @@ class XMLFile extends XMLParent, File {
93115 override string toString ( ) { result = XMLParent .super .toString ( ) }
94116
95117 /** Gets the name of this XML file. */
96- override string getName ( ) { files ( this , result , _ , _ , _ ) }
118+ override string getName ( ) { result = File . super . getAbsolutePath ( ) }
97119
98- /** Gets the path of this XML file. */
99- string getPath ( ) { files ( this , _, result , _, _) }
120+ /**
121+ * DEPRECATED: Use `getAbsolutePath()` instead.
122+ *
123+ * Gets the path of this XML file.
124+ */
125+ deprecated string getPath ( ) { result = getAbsolutePath ( ) }
100126
101- /** Gets the path of the folder that contains this XML file. */
102- string getFolder ( ) {
103- result = this .getPath ( ) .substring ( 0 , this .getPath ( ) .length ( ) - this .getName ( ) .length ( ) )
104- }
127+ /**
128+ * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
129+ *
130+ * Gets the path of the folder that contains this XML file.
131+ */
132+ deprecated string getFolder ( ) { result = getParentContainer ( ) .getAbsolutePath ( ) }
105133
106134 /** Gets the encoding of this XML file. */
107135 string getEncoding ( ) { xmlEncoding ( this , result ) }
@@ -116,8 +144,18 @@ class XMLFile extends XMLParent, File {
116144 XMLDTD getADTD ( ) { xmlDTDs ( result , _, _, _, this ) }
117145}
118146
119- /** A "Document Type Definition" of an XML file. */
120- class XMLDTD extends XMLLocatable , @xmldtd {
147+ /**
148+ * An XML document type definition (DTD).
149+ *
150+ * Example:
151+ *
152+ * ```
153+ * <!ELEMENT person (firstName, lastName?)>
154+ * <!ELEMENT firstName (#PCDATA)>
155+ * <!ELEMENT lastName (#PCDATA)>
156+ * ```
157+ */
158+ class XMLDTD extends @xmldtd {
121159 /** Gets the name of the root element of this DTD. */
122160 string getRoot ( ) { xmlDTDs ( this , result , _, _, _) }
123161
@@ -134,7 +172,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
134172 XMLParent getParent ( ) { xmlDTDs ( this , _, _, _, result ) }
135173
136174 /** Gets a printable representation of this DTD. */
137- override string toString ( ) {
175+ string toString ( ) {
138176 this .isPublic ( ) and
139177 result = this .getRoot ( ) + " PUBLIC '" + this .getPublicId ( ) + "' '" + this .getSystemId ( ) + "'"
140178 or
@@ -143,7 +181,17 @@ class XMLDTD extends XMLLocatable, @xmldtd {
143181 }
144182}
145183
146- /** An XML tag in an XML file. */
184+ /**
185+ * An XML element in an XML file.
186+ *
187+ * Example:
188+ *
189+ * ```
190+ * <manifest xmlns:android="http://schemas.android.com/apk/res/android"
191+ * package="com.example.exampleapp" android:versionCode="1">
192+ * </manifest>
193+ * ```
194+ */
147195class XMLElement extends @xmlelement, XMLParent , XMLLocatable {
148196 /** Holds if this XML element has the given `name`. */
149197 predicate hasName ( string name ) { name = getName ( ) }
@@ -188,7 +236,16 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
188236 override string toString ( ) { result = XMLParent .super .toString ( ) }
189237}
190238
191- /** An attribute that occurs inside an XML element. */
239+ /**
240+ * An attribute that occurs inside an XML element.
241+ *
242+ * Examples:
243+ *
244+ * ```
245+ * package="com.example.exampleapp"
246+ * android:versionCode="1"
247+ * ```
248+ */
192249class XMLAttribute extends @xmlattribute, XMLLocatable {
193250 /** Gets the name of this attribute. */
194251 string getName ( ) { xmlAttrs ( this , _, result , _, _, _) }
@@ -209,8 +266,16 @@ class XMLAttribute extends @xmlattribute, XMLLocatable {
209266 override string toString ( ) { result = this .getName ( ) + "=" + this .getValue ( ) }
210267}
211268
212- /** A namespace used in an XML file */
213- class XMLNamespace extends XMLLocatable , @xmlnamespace {
269+ /**
270+ * A namespace used in an XML file.
271+ *
272+ * Example:
273+ *
274+ * ```
275+ * xmlns:android="http://schemas.android.com/apk/res/android"
276+ * ```
277+ */
278+ class XMLNamespace extends @xmlnamespace {
214279 /** Gets the prefix of this namespace. */
215280 string getPrefix ( ) { xmlNs ( this , result , _, _) }
216281
@@ -220,14 +285,23 @@ class XMLNamespace extends XMLLocatable, @xmlnamespace {
220285 /** Holds if this namespace has no prefix. */
221286 predicate isDefault ( ) { this .getPrefix ( ) = "" }
222287
223- override string toString ( ) {
288+ /** Gets a printable representation of this XML namespace. */
289+ string toString ( ) {
224290 this .isDefault ( ) and result = this .getURI ( )
225291 or
226292 not this .isDefault ( ) and result = this .getPrefix ( ) + ":" + this .getURI ( )
227293 }
228294}
229295
230- /** A comment of the form `<!-- ... -->` is an XML comment. */
296+ /**
297+ * A comment in an XML file.
298+ *
299+ * Example:
300+ *
301+ * ```
302+ * <!-- This is a comment. -->
303+ * ```
304+ */
231305class XMLComment extends @xmlcomment, XMLLocatable {
232306 /** Gets the text content of this XML comment. */
233307 string getText ( ) { xmlComments ( this , result , _, _) }
@@ -242,6 +316,12 @@ class XMLComment extends @xmlcomment, XMLLocatable {
242316/**
243317 * A sequence of characters that occurs between opening and
244318 * closing tags of an XML element, excluding other elements.
319+ *
320+ * Example:
321+ *
322+ * ```
323+ * <content>This is a sequence of characters.</content>
324+ * ```
245325 */
246326class XMLCharacters extends @xmlcharacters, XMLLocatable {
247327 /** Gets the content of this character sequence. */
0 commit comments