diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 6786cd91bb553aa88fb5aedfa0ed19ba78cb999e..c07232575e21a1f42d56d1f4f818d8f13b7994a2 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -3537,7 +3537,11 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
 		str = xmlXPathCastNodeToString(cur);
 		PG_TRY();
 		{
-			result = (xmltype *) cstring_to_text((char *) str);
+			/* Here we rely on XML having the same representation as TEXT */
+			char   *escaped = escape_xml((char *) str);
+
+			result = (xmltype *) cstring_to_text(escaped);
+			pfree(escaped);
 		}
 		PG_CATCH();
 		{
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index 379777aced811a3eb0b9d6a455795da4a04ed13a..5cd602107b22a241dc307584c39bba1efce329e6 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -589,6 +589,18 @@ SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
  {<b>two</b>,<b>etc</b>}
 (1 row)
 
+SELECT xpath('//text()', '<root>&lt;</root>');
+ xpath  
+--------
+ {&lt;}
+(1 row)
+
+SELECT xpath('//@value', '<root value="&lt;"/>');
+ xpath  
+--------
+ {&lt;}
+(1 row)
+
 -- Test xmlexists and xpath_exists
 SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
  xmlexists 
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index 1f17bffc0b2088f2afbb1f9793ea1247a79cbedd..53675f5536fb0fde4149e54c00c347c33b28c37d 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -504,6 +504,18 @@ LINE 1: SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>'...
                             ^
 DETAIL:  This functionality requires the server to be built with libxml support.
 HINT:  You need to rebuild PostgreSQL using --with-libxml.
+SELECT xpath('//text()', '<root>&lt;</root>');
+ERROR:  unsupported XML feature
+LINE 1: SELECT xpath('//text()', '<root>&lt;</root>');
+                                 ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+HINT:  You need to rebuild PostgreSQL using --with-libxml.
+SELECT xpath('//@value', '<root value="&lt;"/>');
+ERROR:  unsupported XML feature
+LINE 1: SELECT xpath('//@value', '<root value="&lt;"/>');
+                                 ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+HINT:  You need to rebuild PostgreSQL using --with-libxml.
 -- Test xmlexists and xpath_exists
 SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
 ERROR:  unsupported XML feature
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index f4e423618ecdae34f24a38177ddb337f7ee17183..3270e15721459a30060d02dd6d4cd04a4582cdd1 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -175,6 +175,8 @@ SELECT xpath('', '<!-- error -->');
 SELECT xpath('//text()', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>');
 SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>', ARRAY[ARRAY['loc', 'http://127.0.0.1']]);
 SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
+SELECT xpath('//text()', '<root>&lt;</root>');
+SELECT xpath('//@value', '<root value="&lt;"/>');
 
 -- Test xmlexists and xpath_exists
 SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');