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 ) }
11+
12+ /**
13+ * DEPRECATED: Use `getLocation()` instead.
14+ *
15+ * Gets the source location for this element.
16+ */
17+ deprecated Location getALocation ( ) { result = this .getLocation ( ) }
1618
1719 /**
18- * Whether this element has the specified location information,
19- * including file path, start line, start column, end line and end column.
20+ * Holds if this element is at the specified location.
21+ * The location spans column `startcolumn` of line `startline` to
22+ * column `endcolumn` of line `endline` in file `filepath`.
23+ * For more information, see
24+ * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
2025 */
2126 predicate hasLocationInfo (
2227 string filepath , int startline , int startcolumn , int endline , int endcolumn
2328 ) {
24- exists ( File f , Location l | l = this .getALocation ( ) |
29+ exists ( File f , Location l | l = this .getLocation ( ) |
2530 locations_default ( l , f , startline , startcolumn , endline , endcolumn ) and
2631 filepath = f .getAbsolutePath ( )
2732 )
2833 }
2934
30- /** Gets a printable representation of this element. */
35+ /** Gets a textual representation of this element. */
3136 abstract string toString ( ) ;
3237}
3338
@@ -36,6 +41,12 @@ class XMLLocatable extends @xmllocatable {
3641 * both of which can contain other elements.
3742 */
3843class XMLParent extends @xmlparent {
44+ XMLParent ( ) {
45+ // explicitly restrict `this` to be either an `XMLElement` or an `XMLFile`;
46+ // the type `@xmlparent` currently also includes non-XML files
47+ this instanceof @xmlelement or xmlEncoding ( this , _)
48+ }
49+
3950 /**
4051 * Gets a printable representation of this XML parent.
4152 * (Intended to be overridden in subclasses.)
@@ -69,7 +80,25 @@ class XMLParent extends @xmlparent {
6980 /** Gets the number of places in the body of this XML parent where text occurs. */
7081 int getNumberOfCharacterSets ( ) { result = count ( int pos | xmlChars ( _, _, this , pos , _, _) ) }
7182
72- /** Append all the character sequences of this XML parent from left to right, separated by a space. */
83+ /**
84+ * DEPRECATED: Internal.
85+ *
86+ * Append the character sequences of this XML parent from left to right, separated by a space,
87+ * up to a specified (zero-based) index.
88+ */
89+ deprecated string charsSetUpTo ( int n ) {
90+ n = 0 and xmlChars ( _, result , this , 0 , _, _)
91+ or
92+ n > 0 and
93+ exists ( string chars | xmlChars ( _, chars , this , n , _, _) |
94+ result = this .charsSetUpTo ( n - 1 ) + " " + chars
95+ )
96+ }
97+
98+ /**
99+ * Gets the result of appending all the character sequences of this XML parent from
100+ * left to right, separated by a space.
101+ */
73102 string allCharactersString ( ) {
74103 result = concat ( string chars , int pos |
75104 xmlChars ( _, chars , this , pos , _, _)
@@ -93,15 +122,21 @@ class XMLFile extends XMLParent, File {
93122 override string toString ( ) { result = XMLParent .super .toString ( ) }
94123
95124 /** Gets the name of this XML file. */
96- override string getName ( ) { files ( this , result , _ , _ , _ ) }
125+ override string getName ( ) { result = File . super . getAbsolutePath ( ) }
97126
98- /** Gets the path of this XML file. */
99- string getPath ( ) { files ( this , _, result , _, _) }
127+ /**
128+ * DEPRECATED: Use `getAbsolutePath()` instead.
129+ *
130+ * Gets the path of this XML file.
131+ */
132+ deprecated string getPath ( ) { result = getAbsolutePath ( ) }
100133
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- }
134+ /**
135+ * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
136+ *
137+ * Gets the path of the folder that contains this XML file.
138+ */
139+ deprecated string getFolder ( ) { result = getParentContainer ( ) .getAbsolutePath ( ) }
105140
106141 /** Gets the encoding of this XML file. */
107142 string getEncoding ( ) { xmlEncoding ( this , result ) }
@@ -116,7 +151,17 @@ class XMLFile extends XMLParent, File {
116151 XMLDTD getADTD ( ) { xmlDTDs ( result , _, _, _, this ) }
117152}
118153
119- /** A "Document Type Definition" of an XML file. */
154+ /**
155+ * An XML document type definition (DTD).
156+ *
157+ * Example:
158+ *
159+ * ```
160+ * <!ELEMENT person (firstName, lastName?)>
161+ * <!ELEMENT firstName (#PCDATA)>
162+ * <!ELEMENT lastName (#PCDATA)>
163+ * ```
164+ */
120165class XMLDTD extends XMLLocatable , @xmldtd {
121166 /** Gets the name of the root element of this DTD. */
122167 string getRoot ( ) { xmlDTDs ( this , result , _, _, _) }
@@ -133,7 +178,6 @@ class XMLDTD extends XMLLocatable, @xmldtd {
133178 /** Gets the parent of this DTD. */
134179 XMLParent getParent ( ) { xmlDTDs ( this , _, _, _, result ) }
135180
136- /** Gets a printable representation of this DTD. */
137181 override string toString ( ) {
138182 this .isPublic ( ) and
139183 result = this .getRoot ( ) + " PUBLIC '" + this .getPublicId ( ) + "' '" + this .getSystemId ( ) + "'"
@@ -143,7 +187,17 @@ class XMLDTD extends XMLLocatable, @xmldtd {
143187 }
144188}
145189
146- /** An XML tag in an XML file. */
190+ /**
191+ * An XML element in an XML file.
192+ *
193+ * Example:
194+ *
195+ * ```
196+ * <manifest xmlns:android="http://schemas.android.com/apk/res/android"
197+ * package="com.example.exampleapp" android:versionCode="1">
198+ * </manifest>
199+ * ```
200+ */
147201class XMLElement extends @xmlelement, XMLParent , XMLLocatable {
148202 /** Holds if this XML element has the given `name`. */
149203 predicate hasName ( string name ) { name = getName ( ) }
@@ -188,7 +242,16 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
188242 override string toString ( ) { result = XMLParent .super .toString ( ) }
189243}
190244
191- /** An attribute that occurs inside an XML element. */
245+ /**
246+ * An attribute that occurs inside an XML element.
247+ *
248+ * Examples:
249+ *
250+ * ```
251+ * package="com.example.exampleapp"
252+ * android:versionCode="1"
253+ * ```
254+ */
192255class XMLAttribute extends @xmlattribute, XMLLocatable {
193256 /** Gets the name of this attribute. */
194257 string getName ( ) { xmlAttrs ( this , _, result , _, _, _) }
@@ -209,7 +272,15 @@ class XMLAttribute extends @xmlattribute, XMLLocatable {
209272 override string toString ( ) { result = this .getName ( ) + "=" + this .getValue ( ) }
210273}
211274
212- /** A namespace used in an XML file */
275+ /**
276+ * A namespace used in an XML file.
277+ *
278+ * Example:
279+ *
280+ * ```
281+ * xmlns:android="http://schemas.android.com/apk/res/android"
282+ * ```
283+ */
213284class XMLNamespace extends XMLLocatable , @xmlnamespace {
214285 /** Gets the prefix of this namespace. */
215286 string getPrefix ( ) { xmlNs ( this , result , _, _) }
@@ -227,7 +298,15 @@ class XMLNamespace extends XMLLocatable, @xmlnamespace {
227298 }
228299}
229300
230- /** A comment of the form `<!-- ... -->` is an XML comment. */
301+ /**
302+ * A comment in an XML file.
303+ *
304+ * Example:
305+ *
306+ * ```
307+ * <!-- This is a comment. -->
308+ * ```
309+ */
231310class XMLComment extends @xmlcomment, XMLLocatable {
232311 /** Gets the text content of this XML comment. */
233312 string getText ( ) { xmlComments ( this , result , _, _) }
@@ -242,6 +321,12 @@ class XMLComment extends @xmlcomment, XMLLocatable {
242321/**
243322 * A sequence of characters that occurs between opening and
244323 * closing tags of an XML element, excluding other elements.
324+ *
325+ * Example:
326+ *
327+ * ```
328+ * <content>This is a sequence of characters.</content>
329+ * ```
245330 */
246331class XMLCharacters extends @xmlcharacters, XMLLocatable {
247332 /** Gets the content of this character sequence. */
0 commit comments