12.11 XML 함수
표 12.15 XML 함수
이름 | 설명 |
---|---|
ExtractValue() | XPath 표기법을 사용하여 XML 문자열에서 값을 추출합니다 |
UpdateXML() | 치환 후의 XML 조각을 반환합니다 |
이 섹션에서는 MySQL에서의 XML 관련 기능에 대해 설명합니다.
--xml
옵션으로 호출하면, mysql 및 mysqldump 클라이언트에서 XML 형식의 출력을 MySQL에서 얻을 수 있습니다. 섹션 4.5.1 "mysql - MySQL 명령 행 도구" 및 섹션 4.5.4 "mysqldump - 데이터베이스 백업 프로그램" 을 참조하십시오.
기본적인 XPath 1.0 (XML Path Language 버전 1.0) 기능을 제공하는 2 개의 함수가 사용 가능합니다. XPath 구문 및 사용법에 대한 일부 기본 정보는이 섹션의 뒷부분에서 제공하지만 이러한 주제에 대한 자세한 설명은이 문서의 범위를 벗어납니다. 최종 정보는 "XML Path Language (XPath) 1.0 표준" 을 참조하십시오. XPath 처음 사용자 나 기본 복습을 원하는 사용자에게 유용한 리소스는 여러 언어로 제공되는 "Zvon.org XPath Tutorial」 입니다.
이러한 기능은 아직 개발 중입니다. XML 및 XPath 기능의 이러한 측면 및 다른 측면은 MySQL 5.6 이상에서 계속 개선합니다. 이러한 논의하고, 질문하고, MySQL XML 사용자 포럼 에서 다른 사용자의 도움을 얻을 수도 있습니다.
이 함수에서 사용되는 XPath 표현식은 사용자 변수 및 로컬 저장 프로그램 변수가 지원됩니다. 사용자 변수는 쉽게 확인됩니다. 저장 프로그램에 대한 로컬 변수는 엄격하게 체크됩니다 (Bug # 26518를 참조하십시오).
사용자 변수 (빠른 검사) 구문
$@
을 사용하는 변수 (즉, 사용자 변수)는 체크되지 않습니다. 변수의 형태가 잘못되어 있거나 변수에 값이 미리 할당되지 않은 경우에도 서버에서 경고 나 오류가 발생하지 않습니다. 이것은 (예)variable_name
$@myvariable
을 사용하여 경고가 발행되지 않기 때문에 ($@myvariable
는 고의로 잘못 한 것입니다), 입력 오류는 사용자가 모든 책임을지는 것을 의미합니다.예 :
mysql>
SET @xml = '<a><b>X</b><b>Y</b></a>';
Query OK, 0 rows affected (0.00 sec) mysql>SET @i =1, @j = 2;
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @i, ExtractValue(@xml, '//b[$@i]');
+------+--------------------------------+ | @i | ExtractValue(@xml, '//b[$@i]') | +------+--------------------------------+ | 1 | X | +------+--------------------------------+ 1 row in set (0.00 sec) mysql>SELECT @j, ExtractValue(@xml, '//b[$@j]');
+------+--------------------------------+ | @j | ExtractValue(@xml, '//b[$@j]') | +------+--------------------------------+ | 2 | Y | +------+--------------------------------+ 1 row in set (0.00 sec) mysql>SELECT @k, ExtractValue(@xml, '//b[$@k]');
+------+--------------------------------+ | @k | ExtractValue(@xml, '//b[$@k]') | +------+--------------------------------+ | NULL | | +------+--------------------------------+ 1 row in set (0.00 sec)저장 프로그램 내의 변수 (엄격한 검사)이 함수를 저장 프로그램 내부에서 호출 할 때 구문
$
을 사용하는 변수를 선언하고 이러한 함수에서 사용할 수 있습니다. 이러한 변수는 정의되어있는 저장 프로그램에 대한 로컬 변수이며, 형식 및 값에 대해 엄격하게 체크됩니다.variable_name
예 :
mysql>
DELIMITER |
mysql>CREATE PROCEDURE myproc ()
->BEGIN
->DECLARE i INT DEFAULT 1;
->DECLARE xml VARCHAR(25) DEFAULT '<a>X</a><a>Y</a><a>Z</a>';
-> ->WHILE i < 4 DO
->SELECT xml, i, ExtractValue(xml, '//a[$i]');
->SET i = i+1;
->END WHILE;
->END |
Query OK, 0 rows affected (0.01 sec) mysql>DELIMITER ;
mysql>CALL myproc();
+--------------------------+---+------------------------------+ | xml | i | ExtractValue(xml, '//a[$i]') | +--------------------------+---+------------------------------+ | <a>X</a><a>Y</a><a>Z</a> | 1 | X | +--------------------------+---+------------------------------+ 1 row in set (0.00 sec) +--------------------------+---+------------------------------+ | xml | i | ExtractValue(xml, '//a[$i]') | +--------------------------+---+------------------------------+ | <a>X</a><a>Y</a><a>Z</a> | 2 | Y | +--------------------------+---+------------------------------+ 1 row in set (0.01 sec) +--------------------------+---+------------------------------+ | xml | i | ExtractValue(xml, '//a[$i]') | +--------------------------+---+------------------------------+ | <a>X</a><a>Y</a><a>Z</a> | 3 | Z | +--------------------------+---+------------------------------+ 1 row in set (0.01 sec)매개 변수 스토어드 루틴 내부의 XPath 식에 사용되는 매개 변수로 전달 된 변수도 엄격한 검사 대상입니다.
사용자 변수 및 저장 프로그램에 로컬 변수를 포함 식은 다른 점 (표기법은 제외)에서는 XPath 1.0 사양에 규정되어있는 변수를 포함 XPath 식의 규칙을 준수해야합니다.
현재 XPath 식을 저장하는 데 사용 된 사용자 변수는 빈 문자열로 처리됩니다. 따라서 사용자 변수로 XPath 식을 저장 할 수 없습니다. (Bug # 32911)
ExtractValue(
xml_frag
,xpath_expr
)ExtractValue()
는 XML 마크 업xml_frag
조각과 XPath 식xpath_expr
(locator라고도합니다)의 2 개의 문자열 인수가 지정된 요소의 자식 또는 XPath 표현식에 일치 된 요소 인 첫 번째 텍스트 노드의 텍스트 (CDATA
)가 반환됩니다. MySQL 5.6.6 이전 버전에서는 XPath 식에 최대로 127 문자 만 포함 할 수 없습니다. 이 제한은 MySQL 5.6.7에서 해제되었습니다. (Bug # 13007062, Bug # 62429)이 함수를 사용하는 것은
/text()
를 추가 한 후xpath_expr
를 사용하여 일치를 실행하는 것과 같습니다. 즉,ExtractValue('<a><b>Sakila</b></a>', '/a/b')
과ExtractValue('<a><b>Sakila</b></a>', '/a/b/text()')
는 같은 결과가 생성됩니다.여러 일치가 발견되면 일치되는 요소의 첫 번째 자식 텍스트 노드의 내용이 공백으로 구분 된 단일 문자열로 (일치하는 순서대로) 반환됩니다.
식과 일치하는 텍스트 노드 (암시 적
/text()
을 포함)이없는 경우 어떤 이유에서도xpath_expr
가 활성화되고xml_frag
가 제대로 중첩 된 닫힌 요소로 구성되어있는 경우 경우 빈 문자열이 반환됩니다. 빈 요소에 일치하는지와 전혀 일치하지 않는 것과는 구분하지 않습니다. 이것은 의도적 인 것입니다.xml_frag
에서 일치하는 요소가 발견되지 않았거나 이러한 요소 찾았지만 자식 텍스트 노드가 포함되지 않았는지를 판단 할 필요가있는 경우 XPathcount()
함수를 사용하는 식 결과를 테스트하십시오. 예를 들어, 다음과 같이 이러한 문 모두 빈 문자열이 반환됩니다.mysql>
SELECT ExtractValue('<a><b/></a>', '/a/b');
+-------------------------------------+ | ExtractValue('<a><b/></a>', '/a/b') | +-------------------------------------+ | | +-------------------------------------+ 1 row in set (0.00 sec) mysql>SELECT ExtractValue('<a><c/></a>', '/a/b');
+-------------------------------------+ | ExtractValue('<a><c/></a>', '/a/b') | +-------------------------------------+ | | +-------------------------------------+ 1 row in set (0.00 sec)다만, 다음의 명령을 사용하면 실제로 일치하는 요소가 있었는지 여부를 확인할 수 있습니다.
mysql>
SELECT ExtractValue('<a><b/></a>', 'count(/a/b)');
+-------------------------------------+ | ExtractValue('<a><b/></a>', 'count(/a/b)') | +-------------------------------------+ | 1 | +-------------------------------------+ 1 row in set (0.00 sec) mysql>SELECT ExtractValue('<a><c/></a>', 'count(/a/b)');
+-------------------------------------+ | ExtractValue('<a><c/></a>', 'count(/a/b)') | +-------------------------------------+ | 0 | +-------------------------------------+ 1 row in set (0.01 sec)중요ExtractValue()
는CDATA
만 반환 일치하는 태그에 포함 된 태그와 그 내용은 반환되지 않습니다 (다음의 예에서val1
로 반환 된 결과를 참조하십시오).mysql>
SELECT
->ExtractValue('<a>ccc<b>ddd</b></a>', '/a') AS val1,
->ExtractValue('<a>ccc<b>ddd</b></a>', '/a/b') AS val2,
->ExtractValue('<a>ccc<b>ddd</b></a>', '//b') AS val3,
->ExtractValue('<a>ccc<b>ddd</b></a>', '/b') AS val4,
->ExtractValue('<a>ccc<b>ddd</b><b>eee</b></a>', '//b') AS val5;
+------+------+------+------+---------+ | val1 | val2 | val3 | val4 | val5 | +------+------+------+------+---------+ | ccc | ddd | ddd | | ddd eee | +------+------+------+------+---------+이 함수는
contains()
과의 비교를 수행하고 다른 문자열 함수 (CONCAT()
등)와 같은 데이터 정렬 집합을 실행하고 그 인수의 데이터 정렬 강제성을 고려할 때 현재 의 SQL 데이터 정렬이 사용됩니다. 이 동작을 제어하는 규칙에 대한 설명은 섹션 10.1.7.5 "식의 데이터 정렬" 을 참조하십시오.(이전에는 대소 문자를 구분하는 바이너리가 항상 사용되고있었습니다.)
다음의 예와 같이,
xml_frag
적절하게 중첩되지 않은 요소와 닫혀 있지 않은 요소가 포함되어 경고가 생성 된 경우NULL
이 반환됩니다.mysql>
SELECT ExtractValue('<a>c</a><b', '//a');
+-----------------------------------+ | ExtractValue('<a>c</a><b', '//a') | +-----------------------------------+ | NULL | +-----------------------------------+ 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Warning Code: 1525 Message: Incorrect XML value: 'parse error at line 1 pos 11: END-OF-INPUT unexpected ('>' wanted)' 1 row in set (0.00 sec) mysql>SELECT ExtractValue('<a>c</a><b/>', '//a');
+-------------------------------------+ | ExtractValue('<a>c</a><b/>', '//a') | +-------------------------------------+ | c | +-------------------------------------+ 1 row in set (0.00 sec)UpdateXML(
xml_target
,xpath_expr
,new_xml
)이 함수는 XML 마크 업
xml_target
의 특정 부분의 일부를 새로운 XML 조각new_xml
으로 대체, 수정 된 XML을 반환합니다. 치환 된xml_target
의 일부는 사용자가 지정한 XPath 식xpath_expr
과 일치합니다. MySQL 5.6.6 이전 버전에서는 XPath 식에 최대로 127 문자 만 포함 할 수 없습니다. 이 제한은 MySQL 5.6.7에서 해제되었습니다. (Bug # 13007062, Bug # 62429)xpath_expr
에 일치하는식이 없으면 이상의 일치가 발견되면,이 함수는 원래xml_target
XML 조각을 반환합니다. 3 개의 인수는 문자열로해야합니다.mysql>
SELECT
->UpdateXML('<a><b>ccc</b><d></d></a>', '/a', '<e>fff</e>') AS val1,
->UpdateXML('<a><b>ccc</b><d></d></a>', '/b', '<e>fff</e>') AS val2,
->UpdateXML('<a><b>ccc</b><d></d></a>', '//b', '<e>fff</e>') AS val3,
->UpdateXML('<a><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val4,
->UpdateXML('<a><d></d><b>ccc</b><d></d></a>', '/a/d', '<e>fff</e>') AS val5
->\G
*************************** 1. row *************************** val1: <e>fff</e> val2: <a><b>ccc</b><d></d></a> val3: <a><e>fff</e><d></d></a> val4: <a><b>ccc</b><e>fff</e></a> val5: <a><d></d><b>ccc</b><d></d></a>
XPath 구문의 자세한 설명과 사용법에 대해서는이 문서의 범위를 벗어납니다. 최종 정보는 "XML Path Language (XPath) 1.0 사양" 을 참조하십시오. XPath 처음 사용자 나 기본 복습을 원하는 사용자에게 유용한 리소스는 여러 언어로 제공되는 "Zvon.org XPath Tutorial」 입니다.
일부 기본적인 XPath 식의 설명과 예는 다음과 같습니다.
/
tag
<
이 루트 요소의 경우에 한해,tag
/><
과 일치합니다.tag
/>예 :
/a
는 바깥 쪽 (루트) 태그에 일치하기 때문에<a><b/></a>
에는 일치가 있습니다. 이 예제에서는 다른 요소의 자식이기 때문에<b><a/></b>
의 안쪽a
요소와 일치하지 않습니다./
tag1
/tag2
<
의 자식이며,tag1
/><
가 루트 요소 인 경우에 한해,tag1
/><
과 일치합니다.tag2
/>예 :
/a/b
는 루트 요소a
의 자식이기 때문에 XML 조각<a><b/></a>
의b
요소와 일치합니다. 이 경우b
는 루트 요소 (기타 요소의 자식)이기 때문에<b><a/></b>
는 일치하지 않습니다. XPath 식에서<a><c><b/></c></a>
에 일치하지 않습니다. 여기서b
는a
의 후손이지만, 실제로는a
의 자식이 아닙니다.이 구성은 3 개 이상의 요소를 확장 할 수 있습니다. 예를 들어, XPath 식
/a/b/c
는 조각<a><b><c/></b></a>
의c
요소와 일치합니다.//
tag
의 모든 인스턴스에 일치합니다.< tag >
예 :
//a
는<a><b><c/></b></a>
<<c><a><b/></a></b>
<<c><b><a/></b></c>
중 하나의a
요소와 일치합니다.//
은/
와 결합 할 수 있습니다. 예를 들어,//a/b
는 조각<a><b/></a>
또는<a><b><c/></b></a>
의b
요소와 일치합니다.참고//
는tag
/descendant-or-self::*/
와 동일합니다. 흔한 실수는 이것과tag
/descendant-or-self::
을 혼동하는 것입니다. 다음과 같이 실제로는 후자의 식에서는 전혀 다른 결과가 생성 될 수 있습니다.tag
mysql>
SET @xml = '<a><b><c>w</c><b>x</b><d>y</d>z</b></a>';
Query OK, 0 rows affected (0.00 sec) mysql>SELECT @xml;
+-----------------------------------------+ | @xml | +-----------------------------------------+ | <a><b><c>w</c><b>x</b><d>y</d>z</b></a> | +-----------------------------------------+ 1 row in set (0.00 sec) mysql>SELECT ExtractValue(@xml, '//b[1]');
+------------------------------+ | ExtractValue(@xml, '//b[1]') | +------------------------------+ | x z | +------------------------------+ 1 row in set (0.00 sec) mysql>SELECT ExtractValue(@xml, '//b[2]');
+------------------------------+ | ExtractValue(@xml, '//b[2]') | +------------------------------+ | | +------------------------------+ 1 row in set (0.01 sec) mysql>SELECT ExtractValue(@xml, '/descendant-or-self::*/b[1]');
+---------------------------------------------------+ | ExtractValue(@xml, '/descendant-or-self::*/b[1]') | +---------------------------------------------------+ | x z | +---------------------------------------------------+ 1 row in set (0.06 sec) mysql>SELECT ExtractValue(@xml, '/descendant-or-self::*/b[2]');
+---------------------------------------------------+ | ExtractValue(@xml, '/descendant-or-self::*/b[2]') | +---------------------------------------------------+ | | +---------------------------------------------------+ 1 row in set (0.00 sec) mysql>SELECT ExtractValue(@xml, '/descendant-or-self::b[1]');
+-------------------------------------------------+ | ExtractValue(@xml, '/descendant-or-self::b[1]') | +-------------------------------------------------+ | z | +-------------------------------------------------+ 1 row in set (0.00 sec) mysql>SELECT ExtractValue(@xml, '/descendant-or-self::b[2]');
+-------------------------------------------------+ | ExtractValue(@xml, '/descendant-or-self::b[2]') | +-------------------------------------------------+ | x | +-------------------------------------------------+ 1 row in set (0.00 sec)*
연산자는 모든 요소와 일치하는 '와일드 카드'로 기능합니다. 예를 들어, 식/*/b
는 XML 조각<a><b/></a>
또는<c><b/></c>
의b
요소와 일치합니다. 그러나b
는 다른 요소의 자식이어야하기 때문에이 식은 단편<b><a/></b>
의 일치는 생성되지 않습니다. 와일드 카드는 임의의 위치에서 사용할 수 있습니다. 식/*/b/*
는 그 자체가 루트 요소가 아닌b
요소의 모든 자식과 일치합니다.|
(UNION
) 연산자를 사용하면 여러 찾기 중 하나와 일치 할 수 있습니다. 예를 들어, 식//b|//c
는 XML 대상의 모든b
및c
요소와 일치합니다.그 속성의 하나 이상의 값에 따라 요소와 일치 할 수 있습니다. 이것은 구문
를 사용하여 수행됩니다. 예를 들어, 식tag
[@attribute
="value
"]//b[@id="idB"]
는 단편<a><b id="idA"/><c/><b id="idB"/></a>
의 두 번째 의b
요소와 일치합니다.
를 포함한 모든 요소에 대해 일치하려면, XPath 식attribute
="value
"//*[
를 사용합니다.attribute
="value
"]복수의 속성 값을 필터링하려면 단순히 여러 특성 비교 절을 연속해서 사용하면됩니다. 예를 들어, 식
//b[@c="x"][@d="y"]
는 지정된 XML 조각의 임의의 장소에서 발생한 요소<bc="x" d="y"/>
에 일치합니다.동일한 속성이 여러 값 중 하나와 일치하는 요소를 찾으려면
|
연산자로 결합 된 여러 로케이터를 사용합니다. 예를 들어,c
속성의 값이 23 또는 17 인 모든b
요소와 일치하려면 식//b[@c="23"]|//b[@c="17"]
을 사용합니다 . 이를 위해//b[@c="23" or @c="17"]
와 같이 논리적or
연산자를 사용할 수도 있습니다.참고or
와|
의 차이점은or
조건을 결합하는 반면|
결과 세트를 결합합니다.
XPath 제한 현재 이러한 함수에서 지원되는 XPath 구문은 다음과 같은 제한의 대상이되고 있습니다.
노드 집합 사이의 비교 (
'/a/b[@c=@d]'
등)는 지원되지 않습니다.표준 XPath 비교 연산자는 모든 지원하고 있습니다. (Bug # 22823)
상대 찾기 식은 루트 노드의 컨텍스트에서 해결됩니다. 예를 들어 다음과 같은 쿼리와 결과를 생각해 보겠습니다.
mysql>
SELECT ExtractValue(
->'<a><b c="1">X</b><b c="2">Y</b></a>',
->'a/b'
->) AS result;
+--------+ | result | +--------+ | X Y | +--------+ 1 row in set (0.03 sec)이 경우 로케이터
a/b
가/a/b
에 해결되어 있습니다.상대 위치는 조건에서도 지원하고 있습니다. 다음의 예에서는
d[../@c="1"]
이/a/b[@c="1"]/d
로 해결되어 있습니다.mysql>
SELECT ExtractValue(
->'<a>
-><b c="1"><d>X</d></b>
-><b c="2"><d>X</d></b>
-></a>',
->'a/b/d[../@c="1"]')
->AS result;
+--------+ | result | +--------+ | X | +--------+ 1 row in set (0.00 sec)스칼라 값 (변수 참조 리터럴, 숫자 및 스칼라 함수 호출을 포함)로 평가하는식이 전에 붙은 위치는 허용되지 않으며 사용하면 오류가 발생합니다.
::
연산자를 다음과 같은 노드 형과 결합하는 것은 지원되지 않습니다.axis
::comment()axis
::text()axis
::processing-instructions()axis
::node()
다만, 다음의 예와 같이 이름의 테스트 (
과axis
::name
등)는 지원됩니다.axis
::*mysql>
SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b');
+-------------------------------------------------------+ | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::b') | +-------------------------------------------------------+ | x | +-------------------------------------------------------+ 1 row in set (0.02 sec) mysql>SELECT ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*');
+-------------------------------------------------------+ | ExtractValue('<a><b>x</b><c>y</c></a>','/a/child::*') | +-------------------------------------------------------+ | x y | +-------------------------------------------------------+ 1 row in set (0.01 sec)경로가 루트 요소를 "위쪽"지도하는 경우 "상하"의 이동이 지원되지 않습니다. 즉, 현재의 요소의 하나 이상의 조상이 루트 요소의 조상이기도 한 경우는 지정된 요소의 조상의 후손으로 일치하는 표현을 사용할 수 없습니다 (Bug # 16321를 참조하십시오).
다음 XPath 함수가 지원되지 않거나 설명했다 같은 알려진 문제가 있습니다.
id()
lang()
local-name()
name()
namespace-uri()
normalize-space()
starts-with()
string()
substring-after()
substring-before()
translate()
다음 축은 지원되지 않습니다.
following-sibling
following
preceding-sibling
preceding
ExtractValue()
및 UpdateXML()
에 인수로 전달 된 XPath 식의 요소 선택기에는 콜론 문자 ( " :
")이 포함되어있을 수 있습니다. 이렇게하면 XML 네임 스페이스 표기법을 사용하여 마크 업 및 사용이 활성화됩니다. 예 :
mysql>SET @xml = '<a>111<b:c>222<d>333</d><e:f>444</e:f></b:c></a>';
Query OK, 0 rows affected (0.00 sec) mysql>SELECT ExtractValue(@xml, '//e:f');
+-----------------------------+ | ExtractValue(@xml, '//e:f') | +-----------------------------+ | 444 | +-----------------------------+ 1 row in set (0.00 sec) mysql>SELECT UpdateXML(@xml, '//b:c', '<g:h>555</g:h>');
+--------------------------------------------+ | UpdateXML(@xml, '//b:c', '<g:h>555</g:h>') | +--------------------------------------------+ | <a>111<g:h>555</g:h></a> | +--------------------------------------------+ 1 row in set (0.00 sec)
이것은 몇 가지 점에서 Apache Xalan 및 기타 일부 파서에서 허용되는 것과 비슷하지만, 이름 공간의 제한이나 namespace-uri()
와 local-name()
함수를 사용해야 하는 것보다 훨씬 간단합니다.
오류 처리 ExtractValue()
와 UpdateXML()
의 어느 경우에도 사용되는 XPath 로케이터가 유효하고, 검색 대상의 XML이 적절하게 중첩 된 닫힌 요소로 구성되어 있어야합니다. locator가 무효 인 경우 다음과 같은 오류가 생성됩니다.
mysql> SELECT ExtractValue('<a>c</a><b/>', '/&a');
ERROR 1105 (HY000): XPATH syntax error: '&a'
xml_frag
가 제대로 중첩 된 닫혀있는 요소로 구성되지 않은 경우에는 다음 예와 같이 NULL
을 반환 경고가 생성됩니다.
mysql>SELECT ExtractValue('<a>c</a><b', '//a');
+-----------------------------------+ | ExtractValue('<a>c</a><b', '//a') | +-----------------------------------+ | NULL | +-----------------------------------+ 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Warning Code: 1525 Message: Incorrect XML value: 'parse error at line 1 pos 11: END-OF-INPUT unexpected ('>' wanted)' 1 row in set (0.00 sec) mysql>SELECT ExtractValue('<a>c</a><b/>', '//a');
+-------------------------------------+ | ExtractValue('<a>c</a><b/>', '//a') | +-------------------------------------+ | c | +-------------------------------------+ 1 row in set (0.00 sec)
UpdateXML()
에 제 3의 인수로 사용되는 대체 용 XML 적절하게 중첩 된 닫혀있는 요소로만 구성되어 있는지 여부를 판단하는 검사되지 않습니다.
XPath 인젝션 코드 주입은 권한과 데이터에 대한 무단 액세스 권한을 얻기 위해 악성 코드가 시스템에 도입 된 경우에 발생합니다. 이것은 사용자가 입력 한 데이터의 형식과 내용에 대해 개발자가 수행 한 가정의 악용을 기반으로합니다. 이것에 관해서는, XPath도 예외는 아닙니다.
이 문제가 발생할 수있는 일반적인 시나리오는 다음과 같은 XPath 식을 사용하여 로그인 이름과 암호 조합을 XML 파일에서 발견 된 것과 일치시킴으로써 승인을 처리하는 응용 프로그램 사례입니다.
// user [login / text () = 'neapolitan'and password / text () = '1c3cr34m'] / attribute :: id
이 XPath 식은 다음과 같은 SQL 문에 해당합니다.
SELECT id FROM users WHERE login = 'neapolitan'AND password = '1c3cr34m';
XPath를 사용하는 PHP 응용 프로그램은 다음과 같이 로그인 프로세스가 처리 될 수 있습니다.
<?php $file = "users.xml"; $login = $POST["login"]; $password = $POST["password"]; $xpath = "//user[login/text()=$login and password/text()=$password]/attribute::id"; if( file_exists($file) ) { $xml = simplexml_load_file($file); if($result = $xml->xpath($xpath)) echo "You are now logged in as user $result[0]."; else echo "Invalid login name or password."; } else exit("Failed to open $file."); ?>
입력시에는 검사가 수행되지 않습니다. 이것은 악의적 인 사용자가 로그인 이름과 암호에 ' or 1=1
을 입력하여 테스트를 "해결"할 수있는 것을 의미합니다. 그 결과 $xpath
가 다음과 같이 평가됩니다.
//user[login/text()='' or 1=1 and password/text()='' or 1=1]/attribute::id
괄호 안의 표현식은 항상 true
로 평가되기 때문에 사실상 XML 문서 내의 모든 user
요소의 id
속성과 일치하는 다음의 식과 같습니다.
//user/attribute::id
이 공격을 방지하는 방법 중 하나는 $xpath
의 정의에 삽입되는 변수 이름을 단순히 인용 부호로 둘러싸뿐입니다. 그러면 Web 폼에서 전달 된 값이 강제로 문자열로 변환됩니다.
$xpath = "//user[login/text()='$login' and password/text()='$password']/attribute::id";
이것은 SQL 주입 공격을 방지하기 위해 권장되는 것이 많은 방법과 동일합니다. 일반적으로 XPath 인젝션 공격을 방지하기 위해 따라야 할 방법은 SQL 주입을 방지 할 수있는 방법과 동일합니다.
응용 프로그램은 테스트되지 않은 사용자 데이터는 허용되지 않습니다.
사용자가 보낸 모든 데이터 유형을 확인합니다. 부정한 형태의 데이터는 거부 또는 변환합니다.
숫자 데이터 범위를 벗어난 값이 포함되어 있지 않은지를 테스트합니다. 범위를 벗어난 값은 자르거나 반올림하거나 거부합니다. 문자열에 잘못된 문자가 포함되어 있지 않은지를 테스트합니다 잘못된 문자가 포함 된 입력은 삭제하거나 거부합니다.
명시 적 오류 메시지는 시스템을 위태롭게 데 사용할 수있는 단서를 무단 사용자에 미칠 수 있기 때문에 출력하지 마십시오. 대신 파일이나 데이터베이스 테이블에 기록합니다.
SQL 인젝션 공격을 사용하면 데이터베이스 스키마에 대한 정보를 얻을 수 있도록 XPath 인젝션을 사용하면 Amit Klein 씨의 논문 'Blind XPath Injection " (PDF 파일 46K 바이트)에 설명 된대로 XML 파일을 스캔하여 구조를 명확하게 할 수 있습니다.
클라이언트에 반환되는 출력을 확인하는 것도 중요합니다. MySQL의 ExtractValue()
함수를 사용하면 무엇이 발생 가능성이 있는지를 검토합니다.
mysql>SELECT ExtractValue(
->LOAD_FILE('users.xml'),
->'//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'
->) AS id;
+-------------------------------+ | id | +-------------------------------+ | 00327 13579 02403 42354 28570 | +-------------------------------+ 1 row in set (0.01 sec)
ExtractValue()
는 여러 일치를 공백으로 구분 된 단일 문자열로 반환하는이 주입 공격하여 users.xml
에 포함 된 모든 유효한 ID가 단일 출력 행으로 사용자에게 제공됩니다 합니다. 추가 보호 수단으로 사용자에게 반환되기 전에 출력 테스트도 실시한다. 다음은 간단한 예제를 보여줍니다.
mysql>SELECT @id = ExtractValue(
->LOAD_FILE('users.xml'),
->'//user[login/text()="" or 1=1 and password/text()="" or 1=1]/attribute::id'
->);
Query OK, 0 rows affected (0.00 sec) mysql>SELECT IF(
->INSTR(@id, ' ') = 0,
->@id,
->'Unable to retrieve user ID')
->AS singleID;
+----------------------------+ | singleID | +----------------------------+ | Unable to retrieve user ID | +----------------------------+ 1 row in set (0.00 sec)
일반적으로 사용자 데이터를 안전하게 반환 지침은 사용자 입력을 받아들이 기위한 지침과 동일합니다. 그들은 다음과 같이 요약 할 수 있습니다.
항상 출력 데이터 형식과 허용되는 값을 테스트합니다.
무단 사용자가 오류 메시지를 표시하는 것을 허용하지 마십시오. 응용 프로그램에 대한 정보가 제공 될 가능성이 있고, 그것을 악용 될 우려가 있습니다.