Copyright © 2025-2026 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
이 문서는 RDF를 위한 Datalog 스타일의 규칙 언어인 SPARQL-RL을 정의합니다.
SPARQL-RL은 입력 RDF 그래프에 대해 선언적 규칙 집합을 평가하여 새로운 RDF 데이터를 생성합니다. 규칙은 SPARQL과 유사한 텍스트 구문으로 작성됩니다.
이 명세는 W3C 데이터 셰이프 워킹 그룹에서 발행했습니다.
이 절에서는 이 문서가 발행된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.
이 문서는 데이터 셰이프 워킹 그룹에서 권고안 트랙을 사용하여 작업 초안으로 발행했습니다.
작업 초안으로 발행되었다고 해서 W3C 및 그 회원이 이를 승인한다는 의미는 아닙니다.
이 문서는 초안 문서이며 언제든 다른 문서로 갱신되거나 대체되거나 폐기될 수 있습니다. 이 문서를 진행 중인 작업이 아닌 다른 것으로 인용하는 것은 적절하지 않습니다. 향후 이 권고안의 갱신에는 새로운 기능이 포함될 수 있습니다.
이 문서는 W3C 특허 정책에 따라 운영되는 그룹에서 작성했습니다. W3C는 해당 그룹의 산출물과 관련하여 이루어진 모든 특허 공개의 공개 목록을 유지하고 있으며, 해당 페이지에는 특허를 공개하는 방법도 포함되어 있습니다. 자신이 알고 있는 특허에 필수 청구항이 포함되어 있다고 판단하는 개인은 W3C 특허 정책 제6절에 따라 해당 정보를 공개해야 합니다.
이 문서는 2025년 8월 18일 W3C 프로세스 문서의 적용을 받습니다.
이 문서는 SPARQL-RL을 소개합니다. 이는 선언적 규칙을 통해 기존 RDF 데이터에서 새로운 RDF 트리플을 도출하는 메커니즘입니다. 이 문서는 규칙 기반 추론의 구문과 의미론을 정의합니다.
SPARQL-RL 구현은 추론 및 질의 연산 중 하나 또는 둘 다를 제공합니다. 추론 연산은 주어진 기본 그래프에 규칙을 적용하고 기본 그래프에 나타나지 않는, 규칙 평가를 통해 도출된 RDF 트리플을 포함하는 추론 그래프를 생성합니다. 추론 그래프와 기본 그래프를 결합하는 것은 선택 사항이며 사용자에게 맡겨집니다. 질의 연산은 주어진 목표 패턴이 규칙을 사용하여 기본 그래프에서 도출될 수 있는지, 그리고 어떻게 도출되는지를 결정합니다.
SPARQL-RL은 규칙의 헤드에 있는 트리플 템플릿에서 사용할 수 있는 빈 노드를 포함하여 새로운 RDF 용어를 생성할 수 있습니다.
SPARQL-RL은 실패에 의한 부정을 지원하며, 이로 인해 규칙이 평가되는 순서에 따라 서로 다른 추론 그래프가 생성될 수 있습니다. 이를 방지하기 위해 규칙은 계층화 기법을 사용하여 평가되며, 이 기법은 규칙 간의 순서를 정해 항상 동일한 추론 그래프가 생성되도록 보장합니다.
SPARQL-RL은 그룹화와 집계를 지원하며, 규칙 본문에서 집계 함수의 결과를 변수에 할당할 수 있습니다.
문맥이 명확한 경우 SPARQL-RL을 SRL이라고 부를 수 있습니다.
다음 명세는 이 문서에서 사용되는 기본 용어를 제공합니다.
이 문서의 RDF 데이터 예제에서는 RDF 1.2 Turtle [RDF12-TURTLE]을 사용합니다.
이 문서에서는 다음 네임스페이스 접두사 바인딩을 사용합니다.
| 접두사 | 네임스페이스 |
|---|---|
rdf: |
http://www.w3.org/1999/02/22-rdf-syntax-ns# |
xsd: |
http://www.w3.org/2001/XMLSchema# |
: |
http://example/ |
문서 전체에서 색상으로 구분된 상자는 SPARQL-RL 구문의 규칙을 포함하거나 Turtle 구문의 RDF 그래프를 포함합니다.
# 이 상자는 규칙을 나타냅니다
# 이 상자는 입력 데이터를 나타냅니다
# 이 상자는 추론된 데이터를 나타냅니다
비규범적으로 표시된 절 외에도 이 명세의 모든 작성 지침, 다이어그램, 예제 및 참고 사항은 비규범적입니다. 이 명세의 나머지 모든 내용은 규범적입니다.
이 문서에서 사용되는 핵심 단어 MAY, MUST 및 MUST NOT은 여기에 표시된 것처럼 모두 대문자로 표기된 경우에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석해야 합니다.
이 명세는 다음에 대한 적합성 기준을 정의합니다.
적합한 SPARQL-RL 문서는 UTF-8 [RFC3629]로 인코딩된 RDF 문자열이며, 7.6 문법에서 정의된 문법과 추가 제약 조건을 준수합니다.
이 명세는 SPARQL-RL 프로세서가 적합하지 않은 SPARQL-RL 문서를 처리하는 방법을 정의하지 않습니다.
이 절은 비규범적입니다.
SPARQL-RL은 기본 그래프와 규칙 집합이 주어지면 새로운 트리플을 추론합니다. 평가의 출력은 기본 그래프에 나타나지 않는 도출된 트리플을 포함하는 추론 그래프입니다.
각 규칙에는 본문이라고 하는 패턴과 헤드라고 하는 결과 템플릿이 있습니다. 규칙은 본문이 결합된 기본 그래프 및 이 시점까지의 실행에서 추론된 모든 트리플과 일치하도록 본문의 변수 값을 찾아 실행됩니다. 그런 다음 이 값은 규칙 헤드의 트리플 템플릿을 인스턴스화하여 새로운 추론 트리플을 생성하는 데 사용됩니다.
규칙은 더 이상 트리플이 추론되지 않을 때까지 실행되며, 새롭게 추론된 트리플을 사용할 수 있게 됨에 따라 규칙은 두 번 이상 실행될 수 있습니다.
SPARQL-RL 실행은 새로운 빈 노드를 포함하여 새로운 RDF 용어를 생성하거나 패턴의 부재를 검사할 때 규칙 실행 순서가 서로 다른 결과를 초래하지 않도록 정의됩니다. 즉, 규칙 실행 순서와 관계없이 동일한 추론 그래프가 생성됩니다.
SPARQL-RL에는 SPARQL 1.2 질의 언어에서 영감을 받은 사람이 이해하기 쉬운 구문이 있습니다. 규칙 집합 평가는 SPARQL과 유사한 요소를 포함하지만, 규칙 실행 순서와 관계없이 동일한 추론 그래프가 생성되도록 세부 사항에는 차이가 있습니다.
이 절의 예제에서는 소프트웨어 구성 요소와 그 종속성을 설명합니다. 프런트엔드는 애플리케이션 서버를 호출하고, 애플리케이션 서버는 알려진 취약점이 있는 데이터베이스를 질의합니다.
하나의 트리플 패턴은 트리플 데이터와 매칭되어 변수에 값을 부여합니다. 패턴에는 세 요소가 있으며, 각각 RDF 용어, 변수, 또는 다음과 같은 패턴입니다. 트리플 용어에 변수가 포함된 패턴입니다.
이 첫 번째 예제에서는 기본 그래프와 규칙 집합에 다음 데이터가 있습니다.
위 규칙을 데이터에 적용하면 다음과 같은 결론을 도출합니다.
:frontend는 :app에 의존하고, :app는
:db에 의존하며, 이는 의존성의 종류와 무관합니다.
그런 다음 의존하는 규칙을 추가하여 :exposedTo 관계를 도출할 수 있습니다.
이 규칙은 다른 규칙이 생성한 :dependsOn 트리플에 의존합니다.
(아래 4.3 규칙
의존성도 참조하세요):
이전 절의 :exposedTo 규칙은 직접적인
의존성에만 도달합니다. :frontend는 :db에 직접 의존하지 않으므로
:frontend에 대한 :exposedTo 트리플은 추론되지 않습니다.
길이에 관계없이 의존성 사슬을 따라 노출을 전파하기 위해,
해당 규칙을 두 규칙으로 대체합니다. 구성 요소는 자신이 가진
취약점에 노출되며, 구성 요소는 직접적인 의존 대상이
노출된 모든 취약점에도 노출됩니다.
이전 예제와 비교하면 다음이 추가됩니다.
:db :exposedTo :vuln1 — 데이터베이스가 자신의
취약점에 노출됩니다 — 및 :frontend :exposedTo :vuln1:
노출은 사슬을 통해 :frontend에 도달하며,
그 의존성 사슬의 길이와는 무관합니다.
이 마지막 규칙은 재귀 규칙입니다. 규칙의 본문이 규칙의 머리부에 의존합니다.
규칙 본문에서 표현식을 사용하여 변수의 값을 제한할 수 있습니다. 이 제한은 본문을 매칭할 때 적용됩니다. 예를 들어 각 취약점의 심각도가 주어지면, 심각한 취약점에 노출된 구성 요소에 상태를 부여할 수 있습니다.
FILTER는 표현식을 평가하며, 현재
변수 바인딩 집합을 표현식이 참으로 평가되면 유지하고,
표현식이 거짓으로 평가되면 현재 변수 바인딩 집합을 버립니다.
이는 다음과 동일합니다.
FILTER 연산(SPARQL)
또한 SPARQL-RL은 SPARQL과 동일한 함수 및 연산자를 다수 제공합니다.
부정은 매칭되지 않아야 하는 패턴을 지정하는 데 사용됩니다. 이를 "실패에 의한 부정"이라고 합니다.
부정 요소를 평가하기 위해 규칙 집합 평가 알고리즘은 해당 패턴과 매칭되는 트리플을 생성할 수 있는 모든 규칙이 부정 요소의 평가 전에 완료되도록 보장합니다. 이를 계층화라고 하며, 부정이 기반으로 삼는 대상에 데이터에서 비롯되든 다른 규칙에서 비롯되든 관련된 모든 가능한 트리플이 포함되도록 보장합니다. 부정을 포함하는 규칙은 이러한 트리플을 생성하는 규칙에 의존한다고 합니다. (아래 4.3 규칙 의존성을 참조하세요).
할당을 통해 규칙은 표현식의 결과를 변수에 할당할 수 있습니다. 이는 규칙 본문에서 이루어지며, 새로운 RDF 용어를 생성하는 데 사용할 수 있습니다. 이때 데이터를 기반으로 합니다.
규칙 머리부에 빈 노드를 사용할 수 있으며, 각각 새로운 빈 노드를 생성합니다. 이는 규칙 평가가 트리플을 생성할 때마다 이루어집니다.
규칙에 포함되는 할당, 빈 노드를 생성하는 규칙에서 평가하는 규칙 머리부, 그리고 템플릿이 있는 규칙에서 포함하는 트리플 용어에 포함된 변수 가 있는 경우, 해당 규칙은 단일 실행 규칙입니다. 이러한 규칙은 자신이 의존하는 데이터를 생성할 수 있는 모든 규칙 이후에 실행되며, 자신이 생성하는 데이터에 의존하는 모든 규칙 이전에 실행됩니다.
이 조건은 이러한 규칙이 자기 자신으로 되돌아가 반복하여 무한한 수의 RDF 용어를 생성하지 않도록 보장합니다.
다음 그룹 요소를 포함하는 규칙은 일회 실행 규칙입니다. 이러한 규칙은 자신이 의존하는 데이터를 생성할 수 있는 모든 규칙이 실행된 후, 자신이 생성하는 데이터에 의존하는 규칙이 실행되기 전에 실행됩니다. 하나의 그룹 요소는 다음의 모든 해 시퀀스를 소비하며, 이는 앞선 규칙 요소가 규칙 본문에서 생성한 것입니다. 그런 다음 이를 그룹 키를 기준으로 그룹화하고 집계 할당을 평가합니다.
출력은 각 해결 매핑이 현재 해결 매핑에 그룹 키와 집계 변수의 값을 추가한 해결 시퀀스입니다.
@@ 예제
SPARQL-RL 규칙 집합은 다른 규칙 집합을 통합할 수 있으며, 이를 위해 해당 URL을 규칙 집합 가져오기에 포함합니다. 이를 통해 규칙을 규칙 집합 간에 공유되는 라이브러리로 구조화할 수 있습니다.
규칙 집합의 IMPORTS 문은 어떤 규칙이든
규칙 집합 내에서 평가되기 전에 처리됩니다. 가져오기 단계에서 가져온 규칙 집합에
자체 가져오기가 있으면, 이들도 재귀적으로 처리됩니다.
규칙 집합을 처리하는 동안 IMPORTS 문을 순회하면
순환 가져오기를 만날 수 있습니다. 규칙 집합은 한 번만 가져옵니다.
가져오기 문 그래프의 순환은 무한 루프를 유발하지 않습니다.
규칙 집합 가져오기 지원은 다음에서 선택 사항입니다. SPARQL-RL 처리기. 자세한 내용은 4.5 처리: 가져오기를 참조하세요.
데이터 블록은 규칙 집합 평가에 RDF 트리플을 직접 제공합니다. 데이터 블록의 트리플은 추론 그래프에 추가되며, 규칙 본문에서 매칭에 사용할 수 있습니다.
예를 들어 규칙 집합은 알려진 사실을 포함하여 제공될 수 있으며, 이 사실은 데이터에서 도출되지 않고 직접 단언됩니다.
데이터 블록은 본문이 비어 있는 규칙과 동등합니다. 그 트리플은 어떠한 규칙도 평가되지 않은 상태에서 추론 그래프의 일부가 됩니다.
규칙 집합 평가 중에는 원래의 대상에만 패턴 매칭을 수행해야 할 수 있습니다. 기본 그래프가 그 대상이며, 추론된 트리플은 대상이 아닙니다.
기본값 설정이 이에 해당하는 예입니다. 규칙은 기본 그래프에 이미 값이 있는지 검사해야 하며, 값이 없으면 규칙은 기본값을 계산할 수 있습니다.
NOT DATA를 사용하면 규칙 본문의 다른 부분에서 추론된 트리플을 매칭할 수 있습니다.
또한 전체 규칙 본문 매칭을 다음 대상으로 수행할 수도 있습니다. 기본 그래프를 대상으로,
WHERE DATA를 사용합니다.
그러면 이러한 규칙은 기본 그래프의 매칭에만 의존합니다.
이 절의 매칭 대상은 기본 그래프입니다.
여기에는 다음에 의해 추가된 트리플이 포함되지 않습니다.
규칙 집합 평가가
다음에서 추가한 트리플입니다. 규칙 집합의 DATA 블록
(3.8 데이터 블록).
규칙은 다음으로 구성됩니다. 규칙 집합. 규칙 집합과 데이터 그래프(즉, 기본 그래프)는 평가의 입력입니다. 출력은 그래프이며, 다음과 같이 부릅니다. 추론 그래프, 이는 평가 과정에서 생성된 트리플의 집합으로, 다음에 나타나지 않는 트리플로 이루어집니다. 기본 그래프.
평가 중에 한 규칙을 기반으로 추론된 트리플은 다른 규칙의 매칭에 사용할 수 있습니다. 규칙 집합 평가는 다음 시점까지 진행됩니다. 더 이상 트리플을 추론할 수 없는 시점이며, 이때 입력은 규칙 집합과 기본 그래프입니다.
평가는 다음 단계로 시작됩니다. 규칙 집합을 준비합니다. 이는 규칙 자체를 평가하기 전에 수행됩니다.
하나의 규칙 집합이 준비되면, 평가는 각각의 계층을 계층화에서 순서대로 가져와, 해당 계층의 규칙을 완료될 때까지 평가하고, 그런 다음 다음 계층으로 이동하는 방식으로 진행됩니다. 규칙 실행으로 트리플이 추론되면, 해당 트리플은 즉시 다른 규칙이 실행될 때 사용할 수 있게 됩니다.
SPARQL-RL 추상 구문은 SPARQL-RL의 논리적 구조입니다. 이는 SPARQL-RL의 실행 알고리즘을 정의하는 데 사용됩니다.
하나의 트리플 템플릿은 각 요소가 다음 중 하나인 3-튜플입니다: 하나의 변수, 하나의 RDF 용어, 또는 다음에 대한 템플릿: 트리플 용어(다음 포함: 변수). 튜플의 두 번째 요소는 IRI 또는 하나의 변수입니다. 트리플 템플릿은 헤드에 나타나며, 해당 규칙에서 다음을 생성하는 데 사용됩니다: RDF 트리플.
.evaldata가 있으며,
일치에 사용할 그래프를 나타냅니다.
그 대상은 부정 요소 본문입니다.
IMPORTS 문에서 가져온 것으로,
평가 중에 포함될 다른 규칙 집합을 위한 것입니다.
.evaldata.
이 플래그는 어떤
그래프를 일치에 사용할지 나타내며, 대상은 트리플 패턴으로, 본문에 있습니다.
규칙을 식별하는 데 도움이 되도록 URI나 빈 노드를 부여할 수 있습니다.
하나의 단일 실행 규칙은 정확히 한 번만 실행되는 규칙으로, 규칙 집합 평가의 특정 시점에 실행됩니다. 하나의 규칙은 단일 실행 규칙에 해당합니다. 다음 중 하나라도 성립하는 경우입니다:
SPARQL-RL은 두 연산을 제공합니다. 추론 및 질의입니다.
질의는 주어진 패턴을 도출할 수 있는지 결정하는 연산이며, 도출의 출발점은 기본 그래프이고, 다음을 사용합니다. 규칙 집합. 또한 하나의 해 시퀀스를 반환하며, 여기서 각 해 매핑은 변수에 대한 RDF 용어를 제공합니다.
질의는 다음을 수행하는 효과를 가집니다. 추론 연산을 수행한 후, 목표 패턴을 다음의 결합 결과와 매칭합니다. 기본 그래프 및 추론 그래프.
해당 질의 연산은 모든 규칙을 평가하지 않을 수 있으며, 대신 질의 목표에 답하는 데 필요한 규칙만 평가할 수 있습니다.
하나의 트리플 패턴 또는 트리플 템플릿에서, 튜플의 위치 1은 비공식적으로 주어라고 부르고, 위치 2는 비공식적으로 술어라고 부르며, 위치 3은 비공식적으로 목적어라고 부릅니다.
시퀀스의 요소인 규칙 요소에는 1부터 번호가 부여됩니다.
규칙 집합과 규칙의 다양한 구성 요소에는 다음 표기법이 사용됩니다.
| 구성 요소 | 용도 |
|---|---|
ruleset.rules |
규칙들로, 규칙 집합에 속합니다. |
ruleset.data |
해당 RDF 그래프는 다음의 합집합으로 형성됩니다: 데이터 블록(규칙 집합 내). |
ruleset.imports |
다음의 집합입니다: 가져오기. 이는 규칙 집합에 속합니다. |
rule.head |
해당 트리플 템플릿들은 규칙 헤드에 속합니다. |
rule.body |
해당 규칙 요소들은 규칙에 속합니다. |
rule.evaldata |
불리언 플래그입니다. false이면, 해당 규칙 본문의 일치 여부를 확인하며, 그 대상은 기본 그래프입니다. |
rule.id |
규칙의 식별자로, 빈 노드 또는 IRI입니다. |
filter.expr |
해당 표현식은 필터 요소에 속합니다. |
assign.var |
해당 할당 변수는 할당 요소에 속합니다. |
assign.expr |
해당 할당 표현식입니다. |
negation.inner |
해당 부정 요소 본문은 하나의 부정 요소에 속합니다. |
negation.evaldata |
불리언 플래그입니다. false이면, negation.inner의 일치 여부를 확인하며,
그 대상은 기본 그래프입니다. |
group.keys |
다음의 집합입니다: 그룹 키. 이는 그룹 요소에 속합니다. |
group.pattern |
해당 그룹 패턴은 그룹 요소에 속합니다. |
group.aggregations |
해당 집계 할당들은 그룹 요소에 속합니다. |
aggregation.variable |
해당 집계 변수는 집계 할당에 속합니다. |
aggregation.function |
해당 집계 함수는 집계 할당에 속합니다. |
올바른 형식은 추상 구문에 대한 조건들의 집합으로, 하나의 규칙 집합에 적용됩니다. 이 조건들은 함께 다음을 보장합니다. 하나의 변수가 헤드에 있는 규칙에서는 그 값이 본문에 정의되어 있다는 점; 각 변수가 필터 요소 또는 할당 표현식에 있을 때 평가 시점에 값을 갖는다는 점; 그리고 각 할당 변수 및 집계 변수가 규칙에서 새로 도입되며 규칙 본문에서 앞서 사용되지 않았다는 점입니다.
S를 규칙 요소의 시퀀스라고 합니다.
elti를 S의 i번째 요소라고 하고, N을 시퀀스의 길이라고 합니다.
V0를 변수 집합이라고 하며, 이를 초기 변수라고 부릅니다. 이 변수들은 시퀀스 S의 초기 변수입니다.
vars(S, i, V0)를 변수들의 집합으로 정의하며, 이 변수들은 시퀀스 S의 i번째 요소 이후에 유효 범위에 있습니다. 이때 초기 변수 V0가 주어집니다. vars(S, i, V0)는 귀납적으로 정의됩니다:
{ avar } ∪ vars(S, i-1,
V0)입니다.
vars(S, V0), 즉 S에서 유효 범위에 있는 변수들의 집합을 vars(S, N, V0)로 정의합니다. 이는 유효 범위에 있는 변수들의 집합이며, 시퀀스의 마지막 요소 이후를 기준으로 합니다.
다음 규칙 요소의 시퀀스 S는 올바른 형식의 시퀀스입니다. 변수 집합 V0가 주어졌을 때, 다음 조건들이 각 i에 대해 충족되는 경우이며, 그 범위는 1부터 N까지입니다:
하나의 규칙은 올바른 형식의 규칙입니다. 다음 조건이 성립하는 경우입니다. 규칙 요소의 시퀀스가 속한 규칙 본문에서, 이 시퀀스가 올바른 형식의 시퀀스이며, 시작 시 V0가 공집합이고, 각 변수가 트리플 템플릿에 있으며, 이 템플릿이 규칙 헤드에 속할 때, 각 변수가 vars(S, V0)의 원소인 경우입니다.
하나의 규칙 집합이 올바른 형식의 규칙 집합인 것은 모든 규칙이 해당 규칙 집합에서 올바른 형식의 규칙인 경우와 그 경우에만 해당합니다.
규칙 R1이 규칙 R2에 의존하는 경우는 두 번째 규칙의 출력이
첫 번째 규칙의 본문 평가에 영향을 미칠 때입니다. 즉, R2의 헤드에는
하나의 트리플 템플릿이 있으며, 이는 다음에 일치하는 트리플을 생성할 수 있습니다:
하나의 트리플 패턴으로, R1의 본문에 있으며,
하나의 트리플 패턴 요소로 나타나거나, 하나의 부정 요소
또는 하나의 그룹 패턴 안에 있습니다.
의존성에는 두 종류가 있습니다:
닫힌 의존성 및 열린
의존성.
닫힌 의존성은 규칙 R2가
규칙 R1이 실행되기 전에 가능한 모든 출력을 생성했음을 보장합니다.
규칙 의존성이 닫혀 있지 않으면 열린 의존성입니다.
이는 첫 번째 규칙 R1이 실행될 수 있게 하며,
그동안 규칙 R2는 추가 트리플을 생성하기 위해 다시 실행될 수 있고,
이에 따라 R1이 R2의 새 트리플로 재평가될 수 있습니다.
플래그 .evaldata가 false로 설정된 규칙은
기본 그래프를 사용하여 매칭하며, 해당 규칙에는 의존성이 없습니다.
이 첫 번째 예제에서 첫 번째 규칙은 열린 의존성을 가집니다. 그 대상은 두 번째 규칙입니다.
이 두 번째 예제에서 첫 번째 규칙은 닫힌 의존성을 가집니다.
그 대상은 두 번째 규칙입니다. 트리플 패턴 ?x :status :criticallyExposed는
다음의 내부에 나타납니다. 부정 요소로서 첫 번째 규칙에 속하며,
다음과 매칭됩니다. 트리플 템플릿으로서 두 번째 규칙의 머리부에 있습니다.
첫 번째 규칙은 두 번째 규칙이
가능한 모든 출력을 생성할 때까지 평가할 수 없습니다.
하나의 트리플 패턴은 트리플 템플릿과 매칭되며, 이는 해당 트리플 템플릿이 트리플을 생성할 수 있고, 해당 트리플이 매칭되는 대상이 해당 트리플 패턴인 경우입니다.
하나의 트리플 패턴이 의존하는 대상은 트리플 템플릿이며, 이는 해당 트리플 패턴이 매칭될 수 있는 대상이 해당 트리플 템플릿인 경우입니다.
규칙 R1은 의존
관계에 있습니다
규칙 R2에 대해 다음 조건이 성립하는 경우입니다.
R1.evaldata가 true이고, 어떤 트리플
패턴이 R1의 본문에 있으며,
그 형태가 트리플 패턴 요소이든,
다음의 내부에 있든:
부정 요소 neg(여기서
neg.evaldata는 true),
또는 그룹 패턴 내부에 있든,
의존하는
트리플 템플릿이
R2의 헤드에 있는 경우입니다.
하나의 규칙 의존성이 규칙 R1에서 규칙
R2로 향할 때, 이는 닫힌 의존성이며,
다음 조건 중 하나라도 성립하는 경우입니다:
하나의 규칙 의존성이 규칙 R1에서 규칙
R2로 향할 때,
이는 열린 의존성이며, 해당 의존성이
닫힌 의존성이 아닌 경우입니다.
트리플 템플릿은
트리플 템플릿의 변수에 대한 값이 존재하여
템플릿의 변수를 값으로 대체했을 때 트리플 T2가 되고,
T2가 T1과
같으면
RDF 트리플 T1을
생성할 수 있습니다.
마찬가지로, 트리플 패턴과 일치하는 트리플 T1은
해당 패턴의 변수에 할당할 값들이 존재하는 경우입니다.
트리플 패턴의 변수를 해당 값으로 치환할 때에는
빈 노드를
변수로 취급하는 경우도 포함되며,
패턴에서 치환한 결과 트리플 T2가 생성되고,
이 T2와 동일한
T1이어야 합니다.
트리플 템플릿 또는 트리플 패턴에서 변수가 두 번 이상 사용되면, 대체할 때 동일한 RDF 용어가 사용됩니다.
트리플 패턴에서 변수를 RDF 용어로 대체하는 것은 트리플 용어 내부의 변수를 대체하는 것도 포함합니다.
규칙 간의 종속성은 종속성 그래프라고 하는 방향 그래프로 표현됩니다. 그래프의 정점은 규칙 집합의 규칙이며, 간선에는 종속성이 열린 종속성인지 닫힌 종속성인지에 따라 open 또는 closed라는 레이블이 지정됩니다.
R1이 R2에 의존하면 규칙 R1에서
규칙 R2로 향하는 간선이 존재하는 방향 그래프입니다.
간선에는 종속성이
열린 종속성인지 닫힌
종속성인지에 따라
open 또는 closed라는 레이블이 지정됩니다.
R1에서 R2로 가는 경로가 존재하면
규칙 R1은 규칙 R2에 대해
전이적 종속성을 가집니다.
종속성 그래프는 기본 그래프의 영향을 받지 않습니다.
다음 알고리즘은 한 가지 가능한 구성 방법을 제시합니다. 그 대상은 의존성 그래프이며, 그 출발점은 규칙 집합입니다. 적합성은 의존성 그래프를 생성하는 데 달려 있으며, 그 그래프는 의존성 그래프의 정의를 충족해야 합니다. 이 절차의 사용 여부에 달려 있지는 않습니다.
define mergeLabel(oldLabel, newLabel):
# 닫힌 의존성이 열린 의존성보다 우선합니다.
if oldLabel == "open" and newLabel == "open":
the result is "open"
else:
the result is "closed"
endif
enddefine
# 출력 -- 규칙 정점과 레이블이 지정된 간선이 있는 의존성 그래프.
define buildDependencyGraph(ruleSet):
# edgeLabelMap은 (R1, R2)를 "open" 또는 "closed"에 매핑합니다
let edgeLabelMap be a map from pair (rule, rule) to label
foreach rule R1 in ruleSet.rules:
let bodyDependencies = {}
if R1.evaldata then:
# 규칙의 각 트리플 패턴 TP를 "open" 또는 "closed"가 필요한 것으로 분류합니다
# 부정 요소나 그룹 패턴 안에 있는지 여부에 따라 분류합니다.
foreach rule element RBE in R1.body:
if RBE is a triple pattern element of triple pattern TP:
let item be a pair (TP, "open")
add item to bodyDependencies
else if RBE is a filter element:
# 아무 작업도 하지 않습니다
else if RBE is a negation element:
if RBE.evaldata then:
foreach triple pattern TP in RBE.inner:
let item be a pair (TP, "closed")
add item to bodyDependencies
endfor
endif
else if RBE is an assignment element:
# 아무 작업도 하지 않습니다
else if RBE is a group element:
foreach triple pattern TP in RBE.pattern:
let item be a pair (TP, "closed")
add item to bodyDependencies
endfor
endif
endfor
endif
foreach pair (triple pattern TP, depLabel) in bodyDependencies:
if R1 is a run-once rule:
set depLabel to "closed"
endif
# 이 트리플 패턴 요소 또는 부정 요소의 의존성을 찾습니다.
foreach rule R2 in ruleSet.rules:
foreach triple template TT in R2.head:
if triple pattern TP matches triple template TT:
let key = (R1, R2)
if edgeLabelMap contains key:
let oldLabel = edgeLabelMap.get(key)
let merged = mergeLabel(oldLabel, depLabel)
edgeLabelMap.set(key, merged)
else:
edgeLabelMap.set(key, depLabel)
endif
endif
endfor
endfor
endfor
endfor
let DP = { }
foreach entry ((R1, R2), label) in edgeLabelMap:
add an edge (R1 -> R2) labeled with label to DP
endfor
the result is DP
enddefine
층화는 하나의 규칙 집합을 순서 있는 시퀀스로 분할하는 과정이며, 그 구성 요소는 층화 계층입니다(다른 명칭은 "strata"이며, 단수형은 "stratum"입니다). 낮은 계층의 규칙은 더 높은 계층의 규칙보다 먼저 평가됩니다.
층화는 다음 사이의 의존성에 제약을 부과합니다: 규칙. 이를 통해 부정 요소, 그룹 요소, 그리고 단일 실행 규칙이 오직 앞선(더 낮은) 계층과 기본 그래프를 사용하여 계산한 결과에만 의존하도록 보장합니다. 이는 단일하고, 명확히 정의되며, 유한한 평가 결과를 보장합니다. 평가 대상은 규칙 집합이며, 주어진 기본 그래프에 대해 평가합니다.
층화 과정은 다른 평가 관련 결정을 내리는 데에도 사용할 수 있습니다. 이 문서는 필요한 조건을 설명합니다. 이는 일관된 평가를 위한 조건이며, 또한 하나의 가능한 층화 구성 방법을 제시합니다. 구현은 조건을 충족해야 합니다. 호환되는 동작을 얻으려면 여기에 설명된 조건을 충족해야 하지만, 제시된 그대로 알고리즘을 구현해야 하는 것은 아닙니다.
하나의 층화 계층 SL은 쌍이며,
서로소인 두 집합으로 구성됩니다.
이들은 규칙 집합 (SL.once, SL.general)입니다.
SL.once는 정확히 단일 실행
규칙들로 이루어지며, 이 규칙들은 해당 계층에 속합니다;
이 규칙들은 각각 평가되며,
다음의 평가 시작 시 정확히 한 번 평가됩니다: 층화 계층.
SL.general은 해당 계층의 나머지 규칙들의 집합이며,
이 규칙들은 새로운 트리플이 더 이상 추론되지 않을 때까지 반복적으로 평가됩니다.
하나의 층화는 하나의 규칙 집합에 대한 것으로, 층화 계층의 시퀀스입니다. 각 규칙은 하나의 규칙 집합에서 정확히 하나의 집합에 속하며, 그 집합은 하나의 층화 계층에 속합니다.
해당 층화 계층들은 하나의 층화에 속하며, 번호가 부여됩니다. 번호는 0부터 시작합니다. 계층 번호는 하나의 규칙에 대해 부여되는 번호이며, 해당 층화 계층, 즉 그 규칙을 포함하는 계층의 번호입니다. 규칙의 계층 번호가 더 작으면, 더 낮은 계층에 있습니다; 규칙의 계층 번호가 더 크면, 더 높은 계층에 있습니다.
층화는 다음 조건이 충족될 때에만 정의됩니다. 하나의 규칙 집합이 이 조건을 충족하지 않으면, 이 명세는 다음의 평가 결과를 정의하지 않습니다: 그러한 규칙 집합.
다음 알고리즘은 하나의 가능한 층화를 제시하며, 그 기반은 오직 규칙 집합입니다.
define stratification(ruleSet):
let DP = Dependency graph for the rule set.
let stratumMap be a map from rule to integer
# 의존성 그래프는 층화 조건을 충족해야 합니다.
# 상한 없는 층화를 검사하는 것은 방어 조치입니다
# 층화 조건 위반에 대비하기 위한 것입니다.
let limit = num rules + 1
let maxStratum = 0
# stratumMap을 초기화합니다
foreach rule in ruleSet.rules:
stratumMap.set(rule, 0)
endfor
let changed = true
while changed:
changed = false
foreach edge E in DP:
# pRule에서 qRule로 향하는 레이블이 있는 간선
let pRule = source of edge
let qRule = destination of the edge
let label = edge label
if label == "open":
if stratumMap.get(pRule) < stratumMap.get(qRule):
stratumMap.set(pRule, stratumMap.get(qRule))
changed = true
endif
endif
if label == "closed":
if stratumMap.get(pRule) <= stratumMap.get(qRule):
let xStratum = 1 + stratumMap.get(qRule)
if xStratum > limit:
# 층화 요구 사항 위반
error "층화 오류"
endif
stratumMap.set(pRule, xStratum)
maxStratum = max(maxStratum, xStratum)
changed = true
endif
endif
endfor
endwhile
# 결과 맵을 초기화합니다.
let stratumRules be a map from integer to rules
foreach i = 0 to maxStratum:
stratumRules.set(i, {})
endfor
# stratumMap에서 계층 번호가 같은 규칙을 모읍니다
foreach rule R in map stratumMap:
let stratumNum = stratumMap.get(R)
add R to stratumRules.get(stratumNum)
endfor
# 각 계층을 once와 general로 분할합니다
let stratumLevels be a sequence of pairs of sets of rules
foreach i = 0 to maxStratum:
let rules = stratumRules.get(i)
let once = { R in rules | R is a run-once rule }
let general = rules \ once
stratumLevels.set(i, pair(once, general))
endfor
the result is stratumLevels
enddefine
의존성 분석의 단계별 적용과 완전한 규칙 집합의 층화부터 평가까지 진행하는 과정은 다음에 제시되어 있습니다: 6.6 풀이 예제.
웹에서 문서를 읽는 작업에는 보안상 영향이 있습니다. 규칙 집합 가져오기 지원 여부는 SPARQL-RL 처리기에서 선택 사항입니다. 또한 구현은 부분적으로 지원할 수 있으며, 예를 들어 일부 규칙 집합의 가져오기만 지원하고 다른 규칙 집합은 지원하지 않거나, 검증된 사본에서만 가져오도록 할 수도 있습니다.
가져오기 처리에는 다음 조건이 적용됩니다.
IMPORTS 문이 포함되어 있으면 이를 거부하고
오류를 알려야 합니다.
IMPORTS 문을 처리할 때 적용됩니다.
하나의 해결된 규칙 집합은 다른 규칙 집합에서 가져오기에 언급된 모든 규칙 집합을 재귀적으로 읽어 생성되며, 이 가져오기는 해당 다른 규칙 집합에 속합니다.
알고리즘의 한 예는 B. 가져오기 알고리즘 예제에서 확인할 수 있습니다.
이 절은 비규범적입니다.
SRL과 SPARQL은 밀접한 관계가 있습니다. SRL은 호환되도록 설계되었으며, 그 대상은 SPARQL이고, SRL의 많은 구문은 다음에서 가져오거나 영감을 받았습니다. SPARQL 패턴 매칭입니다. 그러나 몇 가지 차이점이 있습니다.
SRL에서 RULE 변수는 사용 전에 항상 바인딩되며, 이는
FILTER 또는 SET의 표현식에서 사용되든, 트리플 템플릿에서 사용되든
마찬가지입니다.
이 템플릿은
규칙 머리부에 속합니다. SPARQL CONSTRUCT 질의 및
INSERT 업데이트는
변수가 CONSTRUCT 또는
INSERT 템플릿에 나타나지만 WHERE 절에서 값이 주어지지 않으면 부분적인 결과를 생성합니다.
SET 형식과 SPARQL의 BIND 형식은 서로 다른
오류 처리 동작을 가집니다. SET에서 발생한 오류는
현재 해를 필터링하여 제외하지만, BIND는
현재 해의 변수를 설정하지 않은 채 해당 해를 전달합니다.
SET(?var := expr)는 다음과 동일합니다.
SPARQL에서
BIND(expr AS ?var) 뒤에
FILTER(BOUND(?var))를 사용하는 것입니다.
WHERE 절 구문에는
UNION 또는 OPTIONAL 구문이 포함되지 않습니다.
이러한 SPARQL 요소는 바인딩되지 않은 변수를 초래할 수 있습니다.
UNION 또는 OPTIONAL의 효과는 다음을 사용하여 얻을 수 있습니다.
올바른 형식의 규칙.
그 밖의 차이점은 다음과 같습니다:
NOT 구문은 내부 본문을 트리플
패턴과 필터로 제한하며, 중첩 패턴을 허용하지 않습니다.
NOT은 규칙 본문에서 작성된 위치에서 필터로
실행되며, 이는 SPARQL FILTER NOT EXISTS와 다릅니다.
/ 및 ^를 사용하는 경로만 지원합니다.
이들은 트리플 패턴으로 확장할 수 있습니다.
임의 길이 연산자인 * 및 +는 허용하지 않습니다.
임의 길이 경로는 SPARQL-RL에서 표현할 수 있으며,
더 일반적인 접근 방식인 재귀를 사용합니다.
COALESCE나 BOUND가 없습니다. 해시 함수도 없습니다. 또한
RAND도 없는데, 이는 매번
호출될 때 서로 다른 결과를 반환하기 때문입니다.
NOW()는 허용되며, 동일한
시점을 규칙 집합 평가 전반에 걸쳐 반환하도록 정의됩니다.
BNODE를 사용하면 호출할 때마다 서로 다른 빈 노드가 생성됩니다.
규칙 집합 평가의 결과로 생성되는 추론 그래프는
그래프 동형입니다.
UUID 및 STRUUID를 사용하여 고유 식별자를 생성할 수 있습니다.
규칙은 이렇게 생성된 식별자를 검사하지 않는 것이 좋으며, 오직
트리플을 생성하는 데만 사용해야 합니다.
재현성을 테스트하기 위해 특수한 생성기를 사용할 수 있으며,
이는 NOW의 결과를 테스트하는 것과 유사합니다.
이 절에서는 주어진 데이터에 대해 규칙 집합을 평가한 결과를 정의합니다. 구현에서 이 알고리즘을 사용할 필요는 없습니다. 구현은 동일한 결과를 생성하는 어떤 알고리즘이든 사용할 수 있습니다.
입력: 기본 그래프라고 하는 그래프 G와 규칙 집합 RS. 출력: 추론된 트리플의 RDF 그래프 GI
추론된 트리플에는 기본 그래프에 존재하는 트리플이 포함되지 않습니다.
μ : V → T이며,
여기서 V는 모든 변수의 집합이고
T는 모든 RDF
용어의 집합입니다.
μ의 정의역은
dom(μ)로 나타내며, 이는
V의 부분집합으로, μ가 정의되는 변수들로 이루어집니다. 용어
해는 다음을 의미한다는 것이 명확할 때 사용할 수 있습니다: 해 매핑.
해 매핑을 μ0로 표기하며, 이때
dom(μ0)는 공집합입니다.
해당 치환 함수, 또는 간단히 치환은,
함수
subst(μ, 트리플 패턴)이며
반환하는 것은 하나의 트리플 패턴입니다.
이때 원래 트리플 패턴에서 변수
var가 다음에 속하면,
dom(μ),
해당 변수의 모든 출현은 다음 RDF 용어로 대체되며, 이는
해 매핑이 var에 대해 제공하는 값입니다.
결과 트리플 패턴에 변수가 없으면, 이는 하나의
RDF 트리플입니다.
함수
subst(μ, 트리플 템플릿)도
유사하게 정의됩니다. 변수의 모든 출현은, 해당
트리플 템플릿에서, 다음 RDF 용어로 대체되며, 이는
해 매핑이 var에 대해 제공하는 값입니다.
replaceBlankNodes(트리플 템플릿 목록)이며
이 함수는
다음의 목록을 반환합니다: 트리플 템플릿. 이때 각 빈 노드는
인수 내에서 새 빈 노드로 대체됩니다.
동일한 빈 노드가 여러 번 나타나면,
모두 동일한 새 빈 노드로 대체됩니다.
G를 하나의 RDF 그래프라고 하고, TP를 하나의 트리플 패턴이라고 합니다.
함수 graphMatch(G, TP)는 가능한 모든
해의 집합을 반환합니다. 이 해들을
트리플 패턴에 적용하면 생성되는 트리플은
그래프 G에 속합니다.
S1과 S2를 해라고 합니다.
compatible(μ1, μ2) = true
if forall v in dom(μ1) intersection dom(μ2)
μ1(v) = μ2(v)
compatible(μ1, μ2) = false otherwise
merge(μ1, μ2) = μ such that
μ(v) = μ1(v) if v in dom(μ1)
μ(v) = μ2(v) otherwise
merge(S1, S2) = { μ |
μ1 in S1, μ2 in S2
and compatible(μ1, μ2)
μ = merge(μ1, μ2) }
merge(μ1, μ2)의 정의역은
domain(μ1) ∪ domain(μ2)입니다.
두 해에 공통 변수가 없으면 두 해는 호환되며, 두 해의 병합 결과는 다음의 합집합입니다: μ1과 μ2.
EBV(x)는 유효 불리언 값을 반환하며,
그 대상은 하나의 RDF 용어입니다.
규칙 집합 평가에는 가져온 모든 규칙 집합을 수집하고 4.5 가져오기 처리에 설명된 대로 하나의 결합된 규칙 집합을 구성하는 과정이 포함됩니다.
그런 다음 다음 단계에 따라 결합된 규칙 집합을 평가할 수 있도록 준비합니다.
표현식은 필터 요소에서 사용되든 할당 요소에서 사용되든, 평가에는 하나의 해 매핑이 기준으로 사용됩니다. 해 매핑은 표현식의 각 변수에 대한 RDF 용어 값을 제공합니다. 4.2 올바른 형식 조건의 올바른 형식 요구 사항은 표현식의 모든 변수가 해 매핑에 나타나도록 보장합니다.
define evalFunction(F, μ):
# F는 표현식이며, RDF 용어, 변수 또는 op(expr1, ..., exprN)입니다.
# 여기서 op는 함수 또는 함수 형식입니다.
# μ는 해 매핑입니다.
# 평가 중 오류가 발생하면 evalFunction은 오류를 반환합니다.
if F is an error:
return error
endif
if F is an RDF term:
return F
endif
if F is a variable:
# 올바른 형식 조건에 따라 F ∈ dom(μ)입니다.
return μ(F)
endif
# F는 F = op(expr1, ..., exprN) 형식입니다.
if op is a functional form (e.g., IF, logical-or):
# op에 정의된 방식으로 평가합니다. op는 일부 인수만 평가할 수도 있습니다.
# 예를 들어, IF(c, t, f)는 c를 평가한 다음,
# t 또는 f 중 정확히 하나만 평가합니다.
return the value defined for op over expr1, ..., exprN under μ
endif
# op는 일반 함수이므로 모든 인수를 먼저 평가합니다.
return op(evalFunction(expr1, μ), ..., evalFunction(exprN, μ))
enddefine
define evalAggregate(AGGF, SEQ):
@@
# AGGF는 변수와 해 시퀀스를 인수로 받는
# 집계 함수입니다. RDF 용어 값을 반환합니다.
# DISTINCT는 COUNT에만 허용됩니다.
# COUNT(*)는 특수한 경우입니다.
enddefine
| 집계 함수 | 이에 해당하는 SPARQL 함수 |
|---|---|
COUNT |
SPARQL COUNT
(distinct를 false로 설정) |
COUNT DISTINCT |
SPARQL COUNT
(distinct를 true로 설정) |
MIN |
SPARQL MIN |
MAX |
SPARQL MAX |
SUM |
SPARQL SUM |
집계 함수 계산 중 오류가 발생하면 평가 오류가 발생하며 해당 그룹은 결과에 추가되지 않습니다.
하나의 규칙은 해 시퀀스를 규칙 본문에서 계산한 뒤, 각 해 매핑을 해당 해 시퀀스에서 가져와 트리플을 생성하는 데 규칙 헤드를 사용하는 방식으로 평가됩니다.
규칙 본문에서 빈 노드는 트리플 패턴 내에서 변수처럼 동작합니다. 이는 SPARQL 그래프 패턴 일치와 호환됩니다.
# 규칙 본문을 평가합니다.
# 이 함수는 해 시퀀스를 반환합니다.
define evalRuleElements(B, SEQ, G, GD):
where
B is a sequence of rule elements
SEQ is a solution sequence
G and GD are RDF graphs
foreach rule element rElt in B:
if rElt is a triple pattern element TP:
X = graphMatch(G, TP)
SEQ1 = {}
foreach μ1 in X:
foreach μ2 in SEQ:
if compatible(μ1, μ2):
μ3 = merge(μ1, μ2)
add μ3 to SEQ1
endif
endfor
endfor
endif
if rElt is a filter element F:
SEQ1 = {}
foreach solution μ in SEQ:
let x = evalFunction(F.expr, μ)
if x is not an error and EBV(x) is true:
add μ to SEQ1
endif
endfor
endif
if rElt is a negation element N:
SEQ1 = {}
foreach solution μ in SEQ:
S = sequence{ μ }
if N.evaldata:
NEG = evalRuleElements(N.inner, S, G, GD)
else:
NEG = evalRuleElements(N.inner, S, GD, GD)
endif
if NEG is empty:
add μ to SEQ1
endif
endfor
endif
if rElt is an assignment element A:
SEQ1 = {}
foreach solution μ in SEQ:
let x = evalFunction(A.expr, μ)
if x is not an error:
# 매핑 A.var -> x를 해 μ에 추가합니다.
let μ2 be a solution mapping μ ∪ { (A.var, x) }
add μ2 to SEQ1
else:
# 오류: 해 μ를 제외합니다.
endif
endfor
endif
## COUNT(*)는 어떻게 처리하나요?
if rElt is a group element GRP:
SEQ1 = {}
foreach solution μ in SEQ:
let μp be the restriction of μ to GRP.keys
let SEQX = evalRuleElements(GRP.pattern, { μp }, G, GD)
# 해 매핑을 그룹에 배정합니다.
let KGRP = empty map of solution mappings to solution sequences
foreach solution μx in SEQX:
let μk be the restriction of μx to GRP.keys
if KGRP[μk] is defined:
add μx to the solution sequence KGRP[μk]
else:
KGRP[μk] = solution sequence of one element μx
endif
endfor
# 각 그룹에 대해 집계 함수를 계산하고,
# 현재 해 매핑 μ를 그룹 키와
# 집계 할당 결과로 확장합니다.
foreach key K of map KGRP:
let X be the solution sequence of KGRP[K]
let Z be an empty solution mapping
foreach aggregation function F in GRP.aggregations:
let V = calculate F.function(X)
add solution mapping (F.var, V) to Z
endfor
Z = merge(Z, K)
Z = merge(Z, μ)
add Z to SEQ1
endfor
endfor
endif
SEQ = SEQ1
endfor
return SEQ
enddefine
define evalRule(R, G, GD):
where
R is a well-formed rule
G and GD are RDF graphs
let B be R.body
treating 빈 노드를 변수로.
# 어떤 변수도 매핑하지 않는 해 하나로 이루어진 해 시퀀스입니다.
let SEQ0 be the solution sequence { μ0 }
if R.evaldata:
let SEQ = evalRuleElements(B, SEQ0, G, GD)
else:
let SEQ = evalRuleElements(B, SEQ0, GD, GD)
endif
# 규칙 헤드를 평가합니다.
let OUT = empty set
foreach μ in SEQ:
let S = {}
# 각 빈 노드를 새 빈 노드로 바꾼 규칙 헤드입니다.
let HT = replaceBlankNodes(R.head)
foreach triple template TT in HT:
let triple = subst(μ, TT)
add triple to S
endfor
OUT = OUT ∪ S
endfor
return OUT
enddefine
OUT에는 기본 그래프에도 있는 트리플이 포함될 수 있습니다.
하나의 규칙 집합을 평가하는 것은 해당 규칙 집합의 각 계층을 실행하는 것으로 정의되며, 각 계층은 해당 규칙 집합의 계층화에 속하고, 다음 계층으로 이동하기 전에 순서대로 완전히 실행되어야 합니다. 계층은 이러한 순서에 따라 실행됩니다. 하나의 계층은 먼저 해당 계층의 각 일회 실행 규칙을 평가한 다음, 해당 계층의 일반 규칙을 새로운 트리플이 더 이상 생성되지 않을 때까지 반복해서 평가합니다.
let G0 be the input base graph
let RS be the rule set
let D be the graph of all DATA triples in RS
Apply stratification to RS
let LS be the sequence of layers after stratification
# 추론 그래프
let GI = { t ∈ D | t ∉ G0 }
# 평가 그래프: 기본 그래프와 데이터 블록
let GE = G0 ∪ D
foreach stratum ST in LS:
foreach rule R in ST.once:
let X = evalRule(R, GE, G0)
let Y = { t ∈ X | t ∉ GE }
GI = GI ∪ Y
GE = GE ∪ Y
endfor
let finished = false
while ! finished:
finished = true
foreach rule R in ST.general:
let X = evalRule(R, GE, G0)
let Y = { t ∈ X | t ∉ GE }
if Y is not empty:
finished = false
GI = GI ∪ Y
GE = GE ∪ Y
endif
endfor
endwhile
endfor
the result is GI
이 절은 비규범적입니다.
이 절에서는 완전한 규칙 집합의 평가 과정을 단계별로 살펴봅니다. 즉, 규칙 종속성을 결정하고 (4.3 규칙 종속성), 계층화를 계산하고 (4.4 계층화), 각 계층을 차례로 평가하여 추론 그래프를 생성합니다 (6.5 규칙 집합 평가).
이 예제에서는 소프트웨어 구성 요소와 그 종속성을 설명합니다.
프런트엔드는 애플리케이션 서버에 의존하고, 애플리케이션 서버는
데이터베이스와 로깅 라이브러리에 의존합니다. 데이터베이스에는 알려진
취약점이 있습니다. 규칙은 종속성 체인을 따라 취약점에 대한 노출을
전파하고, 심각한 취약점에 노출된 구성 요소에
:criticallyExposed 상태를 부여하고, 심각하지 않은 구성 요소에
:safeToDeploy 상태를 부여하며, 심각하게 노출된 각 구성 요소에 대한
알림을 생성합니다.
(실제로 취약점이 구성 요소에 영향을 미치는지 여부는
배포된 버전에 따라 달라집니다. 이 예제에서는 버전을 생략하고
취약점을 직접 명시합니다.)
간결성을 위해 기본 그래프에서는
3.1 트리플
패턴에서처럼 더 구체적인 관계에서 도출하는 대신
:dependsOn 트리플을 직접 명시합니다.
규칙은 주석에서 R1부터 R5까지의 레이블이 지정되어 있으며,
이 절의 나머지 부분에서는 이러한 레이블로 참조됩니다.
이 규칙들은
3.2 재귀부터
3.5 할당
및 RDF 용어 생성까지에서 소개한 규칙입니다.
규칙 집합에는 IMPORTS가 없으므로 가져오기 처리를 거쳐도
변경되지 않으며, DATA 블록도 없으므로 평가는
기본 그래프만으로 시작됩니다.
어떤 규칙이 어떤 규칙에 의존하는지 결정하기 위해 각 규칙 본문의 각 트리플 패턴을 모든 규칙 헤드의 트리플 템플릿과 비교합니다 (4.3 규칙 종속성).
R1의 본문은 단일 트리플 패턴
?x :hasVulnerability ?v입니다. 어떤 규칙 헤드에도
술어가 :hasVulnerability인 트리플을 생성할 수 있는 트리플 템플릿이 없으므로,
이 패턴은 데이터에만 매칭될 수 있습니다.
R1에는 종속성이 없습니다.
R2의 본문에는 두 개의 트리플 패턴이 있습니다.
?x :dependsOn ?y는 어떤 규칙 헤드와도 매칭되지 않으므로
데이터에만 매칭됩니다. ?y :exposedTo ?v는 R1의 헤드 템플릿
?x :exposedTo ?v과 매칭되고, R2 자체의 헤드와도 매칭됩니다.
두 출현 모두 트리플 패턴 요소이며
(부정 요소 안에 나타나지 않고,
R2도
한 번 실행되는 규칙이 아닙니다), 따라서
R2는 R1에 대해 열린 종속성을 가지며
자신에 대해서도 열린 종속성을 가집니다.
R2가 자신에게 의존하므로 R2는 재귀 규칙입니다.
R3의 본문에서 패턴 ?x :exposedTo ?v는
R1과 R2의 헤드와 매칭되므로 R3는 각각에 대해
열린 종속성을 가집니다. 패턴 ?v :severity ?s는 어떤
규칙 헤드와도 매칭되지 않습니다.
R4의 본문에서 패턴 ?x rdf:type :Component는
어떤 규칙 헤드와도 매칭되지 않습니다. 술어가
rdf:type인 유일한 헤드 템플릿은 R5에 있으며, 그 목적어
:Notification은 :Component와 다른 RDF 용어이므로
생성된 어떤 트리플도 매칭될 수 없습니다.
패턴 ?x :status :criticallyExposed은
부정 요소
NOT { ?x :status :criticallyExposed } 안에 나타나며
R3의 헤드 템플릿과 매칭됩니다. 패턴이
부정 요소에 나타나므로 R4는 R3에 대해 닫힌
종속성을 가집니다.
R5의 본문에서 패턴 ?x :status :criticallyExposed은
R3의 헤드와 매칭됩니다. R5의 헤드에는
빈 노드가 있으므로, 이 패턴이 일반적인
트리플 패턴 요소임에도 불구하고
R3에 대한 종속성은 닫힌 종속성입니다.
어떤 규칙 본문의 패턴도
R5의 헤드 템플릿과 매칭되지 않으므로 어떤 규칙도 R5에 의존하지 않습니다.
따라서 종속성 그래프에는 5개의 정점과 6개의 간선이 있습니다.
R2 → R1 (열림)
R2 → R2 (열림)
R3 → R1 (열림)
R3 → R2 (열림)
R4 → R3 (닫힘)
R5 → R3 (닫힘)
R4와 R5는 R1 또는
R2에 직접적으로 의존하지 않지만, 각각 R3을 통해 두 규칙 모두에 대한
전이적 종속성을 가집니다.
그래프의 유일한 순환은 자기 자신을 향하는 간선 R2 → R2이며,
이는 열린 종속성입니다. 어떤 순환에도 닫힌
종속성이 포함되지 않으므로 계층화 조건이
충족되며
규칙 집합에는 잘 정의된 결과가 있습니다.
계층화 알고리즘에 따라 모든 규칙은 계층 0에서 시작합니다. 그런 다음 아무것도 변경되지 않을 때까지 간선을 반복해서 검사합니다.
R4 → R3
(닫힘)는 R4와 R3가 모두 계층 0에 있으므로
R4를 계층 1로 이동시킵니다. 마찬가지로 간선 R5 → R3
(닫힘)는 R5를 계층 1로 이동시킵니다.
간선을 한 번 더 순회해도 변경되는 내용이 없으므로 계층이
확정됩니다. 그런 다음 각 계층은
한 번 실행되는 규칙과 일반 규칙으로 나뉩니다.
R5는 헤드에 빈
노드가 있으므로 한 번 실행되는 규칙입니다. 규칙 집합의
다른 규칙 중 한 번 실행되는 규칙은 없습니다.
계층화는 다음과 같습니다.
R1, R2, R3; 한 번 실행되는 규칙 없음R5; 일반 R4
이 순서는 더 높은 계층에 있는 규칙의 의도를 반영합니다.
구성 요소를 배포해도 안전한지, 그리고 어떤
구성 요소에 알림이 필요한지는
모든 :status :criticallyExposed 트리플이 도출된 후에만 결정할 수 있습니다.
이 트리플을 도출하는 규칙 R3는 바로 아래 계층에서,
자신에게 데이터를 제공하는 규칙 R1 및 R2와 함께 완료됩니다.
평가는
6.5 규칙 집합
평가의 알고리즘을 따릅니다.
평가 그래프 GE는 기본 그래프로 시작하고
추론 그래프 GI는 비어 있는 상태로 시작합니다. 각 계층은 순서대로
완료될 때까지 평가됩니다. 계층의 규칙은
패스 단위로 평가되며, 한 패스에서 새로운 트리플이 생성되지 않을 때까지 패스를 반복합니다.
알고리즘은 한 패스 내에서 계층의 규칙이 평가되는 순서를
정하지 않습니다. 이 실행 과정에서는
R1, R2, R3 순서를 사용합니다. 다른 순서는 동일한
추론 결과를 서로 다른 수의 패스에 분산시킬 수 있지만,
계층 0이 완료될 때까지 실행되므로 동일한 최종 그래프를 생성합니다.
이 규칙 집합에는 DATA 블록이 없으므로 평가의 모든 시점에서
GE는 G0와 GI를 더한 것입니다. 따라서 실행 과정에서는
GI만 추적하며, 평가가 진행됨에 따른 상태와
각 새 트리플을 생성한 규칙을 표시합니다.
계층 0, 첫 번째 패스.
R1: 본문이
:db :hasVulnerability :vuln1과 매칭되어
?x = :db와 ?v = :vuln1이 바인딩됩니다.
헤드는 :db :exposedTo :vuln1을 생성합니다.
이 트리플은 GE에 없으므로 GE와 GI에 추가됩니다.
R2: 본문은 ?x :dependsOn ?y와
?y :exposedTo ?v를 조인합니다. 이제 GE에는
:db :exposedTo :vuln1이 있으므로 조인에서 하나의 솔루션이 나옵니다.
?x = :app, ?y = :db, ?v = :vuln1입니다
(:app :dependsOn :db에서 도출됩니다).
헤드는 :app :exposedTo :vuln1을 생성하며, 이는 새 항목이므로
추가됩니다. 아직 :frontend에 대한 솔루션은 없습니다.
이 R2 평가가 시작될 때는
:app :exposedTo :vuln1이 GE에 없었기 때문입니다.
R3: 이제 ?x :exposedTo ?v는 :db와
:app에 대해 매칭됩니다.
:vuln1 :severity 9.1과 조인하고
FILTER(?s >= 9.0)을 적용하면 두 솔루션이 모두 유지됩니다.
헤드는 :db :status :criticallyExposed와
:app :status :criticallyExposed를 생성하며, 둘 다 새 항목입니다.
# 계층 0의 첫 번째 패스 후 GI
:db :exposedTo :vuln1 . # 새 항목 (R1)
:app :exposedTo :vuln1 . # 새 항목 (R2)
:db :status :criticallyExposed . # 새 항목 (R3)
:app :status :criticallyExposed . # 새 항목 (R3)
새 트리플이 생성되었으므로 계층 0의 평가는 다음 패스로 계속됩니다.
계층 0, 두 번째 패스.
R1: 이전과 동일하게 매칭됩니다. :db :exposedTo :vuln1은 이미
GE에 있으므로 새로 생성되는 항목이 없습니다.
R2: 이제 조인에서는
?x = :frontend, ?y = :app, ?v = :vuln1도 나오며,
새 트리플 :frontend :exposedTo :vuln1을 생성합니다.
노출이 종속성 체인을 따라 두 단계를 이동하는 데
두 번의 패스가 필요했습니다.
R3: 새 트리플
:frontend :status :criticallyExposed을 생성합니다.
# 계층 0의 두 번째 패스 후 GI
:db :exposedTo :vuln1 .
:app :exposedTo :vuln1 .
:frontend :exposedTo :vuln1 . # 새 항목 (R2)
:db :status :criticallyExposed .
:app :status :criticallyExposed .
:frontend :status :criticallyExposed . # 새 항목 (R3)
계층 0, 세 번째 패스.
이제 모든 규칙의 모든 솔루션은 이미
GE에 있는 트리플만 생성합니다. GI는 변경되지 않습니다.
새로운 트리플이 없으므로 계층 0이 완료됩니다. 즉, 도출할 수 있는
모든 :exposedTo 트리플과 모든 :status :criticallyExposed 트리플이
도출되었습니다.
계층 1, 한 번 실행되는 규칙. 이 계층의 한 번 실행되는 규칙이 먼저 평가되며, 각각 정확히 한 번 평가됩니다.
R5: 본문은 세 개의 :status :criticallyExposed
트리플과 매칭되어 ?x = :db, ?x = :app,
?x = :frontend 솔루션을 제공합니다. 각 솔루션에 대해 헤드를
인스턴스화하면 새로운 빈 노드가 생성되어 솔루션마다
두 개의 트리플이 생성되며, 이들은 심각하게 노출된 각
구성 요소에 대한 알림입니다. 이후 이 계층의 일반 규칙이
반복해서 평가되더라도 R5는 다시 평가되지 않습니다.
계층 1, 일반 규칙의 첫 번째 패스.
R4: 패턴 ?x rdf:type :Component는
:frontend, :app, :db, :logger와 매칭됩니다.
(방금 R5가 생성한 rdf:type :Notification 트리플과는
매칭되지 않습니다.)
부정 요소 NOT { ?x :status :criticallyExposed }는
:frontend, :app, :db에 대한 솔루션을 거부합니다.
GE가 각각에 대한 :status :criticallyExposed 트리플을 포함하기 때문입니다.
?x = :logger 솔루션만 남으며, 새로운
트리플 :logger :status :safeToDeploy을 생성합니다.
# 계층 1 후 GI
:db :exposedTo :vuln1 .
:app :exposedTo :vuln1 .
:frontend :exposedTo :vuln1 .
:db :status :criticallyExposed .
:app :status :criticallyExposed .
:frontend :status :criticallyExposed .
_:n1 rdf:type :Notification . # 새 항목 (R5)
_:n1 :concerns :db . # 새 항목 (R5)
_:n2 rdf:type :Notification . # 새 항목 (R5)
_:n2 :concerns :app . # 새 항목 (R5)
_:n3 rdf:type :Notification . # 새 항목 (R5)
_:n3 :concerns :frontend . # 새 항목 (R5)
:logger :status :safeToDeploy . # 새 항목 (R4)
계층 1, 일반 규칙의 두 번째 패스.
새로운 트리플이 없습니다. 평가가 완료되며, 위에 표시된 GI가 결과
추론 그래프입니다.
이러한 결과를 신뢰할 수 있게 하는 것은 계층화입니다.
:frontend :status :criticallyExposed이 도출되기 전인
계층 0의 첫 번째 패스 중에 평가되었다면 R4는
:frontend :status :safeToDeploy이라고 잘못 결론 내렸을 것이며,
R5는 :db와 :app에 대한 알림은 생성했지만
:frontend에 대해서는 생성하지 않았을 것입니다.
두 규칙 모두 계층 1까지 지연하면 완전한
:status :criticallyExposed 트리플 집합을 볼 수 있으므로,
각 계층 내에서 규칙이 평가되는 순서는
최종 결과에 영향을 미치지 않습니다.
SPARQL-RL 문서는
RDF 문자열이며, UTF-8 [RFC3629]로
인코딩되고,
문법과 추가 제약 조건을 준수합니다.
이러한 문법과 제약 조건은 다음 절에 정의되어 있습니다:
7.6 문법. 허용되는 문자는
유니코드 스칼라 값뿐이며,
그 범위는 U+0000에서 U+D7FF까지
및 U+E000에서 U+10FFFF까지로
제한됩니다.
따라서
서로게이트 코드 포인트, 즉
U+D800에서
U+DFFF까지의 범위는 제외됩니다.
버전 레이블은 SPARQL-RL의 구문 및 의미론에 대한 적합성을 식별하는 문자열입니다.
| 버전 레이블 |
|---|
| "1.2" |
버전 선언은 힌트입니다. 이 선언은 문서의 앞부분에, 해당 버전에 의존하는 모든 기능보다 먼저 제시하는 것이 좋습니다.
여러 VERSION 지시문이
하나의 SPARQL-RL 문서에 나타날 수 있습니다.
각 지시문은 해당 지시문 다음에 나오는 문서 부분에 적용되며,
다른 지시문을 만나거나 문서의 끝에 도달할 때까지 적용됩니다.
버전 레이블은 version
매개변수로도 지정할 수 있으며, 이 매개변수는
미디어 유형에 속합니다. 현재 적용되는
VERSION 지시문이 없으면,
미디어 유형의 일부로 지정된 버전을 고려합니다.
공백
(생성 규칙 WS)은
그렇지 않으면 하나의 터미널로 잘못
인식될 두 터미널을 구분하는 데 사용됩니다.
아래에서 대문자로 표기된 규칙 이름은 공백이
중요한 위치를 나타내며, 이러한 규칙들은
SPARQL-RL 파서를 구성하기 위한 터미널의 한 가지 선택이 됩니다.
생성 규칙
String에서는 공백이 중요합니다.
주석은
IRIREF,
STRING_LITERAL1,
STRING_LITERAL2,
STRING_LITERAL_LONG1 또는
STRING_LITERAL_LONG2
외부에 있는 #로 시작하며,
줄의 끝(
LF 또는
CR로 표시됨)까지
계속됩니다. 주석 마커 뒤에 줄의 끝이 없으면 파일의 끝까지 계속됩니다.
주석은 공백으로 취급됩니다.
상대 IRI 참조는 통합 자원 식별자(URI): 일반 구문 [RFC3986]에 따라 기준 IRI를 사용하여 제5.2절의 기본 알고리즘만으로 해석됩니다. 구문 기반 정규화나 스킴 기반 정규화 (RFC3986의 제6.2.2절 및 제6.2.3절에 설명됨)는 수행되지 않습니다. IRI 참조에서 추가로 허용되는 문자는 국제화 자원 식별자 (IRI) [RFC3987] 제6.5절에 따라 URI 참조에서 예약되지 않은 문자를 처리하는 것과 동일한 방식으로 처리됩니다.
BASE
지시문은 [RFC3986]
제5.1.1절, "콘텐츠에 포함된 기준
URI"에 따라
상대 IRI 참조를 해석하는 데 사용되는 기준 IRI를
정의합니다.
제5.1.2절, "캡슐화 엔티티의 기준
URI"는
범위 내 기준 IRI가 xml:base 지시문이 있는 SOAP 봉투 또는
Content-Location 헤더가 있는 MIME 멀티파트 문서와 같은
캡슐화 문서에서 유래할 수 있는 방법을 정의합니다.
5.1.3, 검색
URI의 기준 "URI"에서 식별되는 "검색 URI"는
특정 SPARQL-RL 문서를 가져온 URL입니다.
위의 어느 것도 기준 URI를 지정하지 않으면 기본
기준 URI(제5.1.4절, "기본 기준 URI")가
사용됩니다.
각 BASE 지시문은 이전 기준 URI를 기준으로
새로운 범위 내 기준 URI를 설정합니다.
SPARQL-RL 문서에서는 세 가지 형태의 이스케이프가 사용됩니다.
숫자 이스케이프 시퀀스는 유니코드 코드 포인트의 값을 나타냅니다.
숫자 이스케이프 시퀀스는
유니코드 서로게이트의 범위인
U+D800에서 U+DFFF까지의
코드 포인트 값을 생성해서는 MUST NOT 됩니다.
| 이스케이프 시퀀스 | 유니코드 코드 포인트 |
|---|---|
\u hex
hex
hex
hex
|
네 개의 16진수 숫자를 최상위 자릿수에서 최하위 자릿수 순으로 해석하여
인코딩된 값에 해당하는,
U+0000에서 U+D7FF까지
및 U+E000에서 U+FFFF까지의
범위에 있는 유니코드 코드 포인트입니다.
|
\U hex
hex
hex
hex
hex
hex
hex
hex
|
여덟 개의 16진수 숫자를
최상위 자릿수에서 최하위 자릿수 순으로 해석하여 인코딩된 값에 해당하는,
U+0000에서
U+D7FF까지
및 U+E000에서 U+10FFFF까지의
범위에 있는
유니코드 코드 포인트입니다.
|
여기서 hex는 16진수 문자입니다.
HEX ::= [0-9] | [A-F] | [a-f]
문자열 이스케이프 시퀀스는 문자열 리터럴에서 전통적으로 이스케이프되는 문자를 나타냅니다.
| 이스케이프 시퀀스 | 유니코드 코드 포인트 |
|---|---|
\t |
U+0009 |
\b |
U+0008 |
\n |
U+000A |
\r |
U+000D |
\f |
U+000C |
\" |
U+0022 |
\' |
U+0027 |
\\ |
U+005C |
예약 문자 이스케이프 시퀀스는
\ 뒤에
~.-!$&'()*+,;=/?#@%_ 문자 중 하나가 오는 형식이며,
\의
오른쪽에 있는 문자를 나타냅니다.
| 숫자 이스케이프 |
문자열 이스케이프 |
예약 문자 이스케이프 |
|
|---|---|---|---|
IRI,
RDF 용어,
PREFIX
또는 BASE 선언으로 사용됨
|
예 | 아니요 | 아니요 |
| 로컬 이름 | 아니요 | 아니요 | 예 |
| 문자열 | 예 | 예 | 아니요 |
%-인코딩된 시퀀스는
IRI의 문자 범위에 속하며
로컬 이름에서는 명시적으로 허용됩니다.
이러한 시퀀스는 %
뒤에 두 개의 16진수 문자가 오는 형태이며, 동일한
세 문자 시퀀스를 나타냅니다. 이러한 시퀀스는 처리 중에
디코딩되지 않습니다.
<http://a.example/%66oo-bar>로 작성된 용어는
IRI http://a.example/%66oo-bar를 나타내며
IRI http://a.example/foo-bar를 나타내지 않습니다.
접두사
PREFIX ex: <http://a.example/>와 함께
ex:%66oo-bar로 작성된 용어도
IRI http://a.example/%66oo-bar를 나타냅니다.
여기에서 사용되는 EBNF는 XML 1.0 [EBNF-NOTATION]에 정의되어 있습니다.
참고 사항:
[1] |
RuleSet |
::= | RuleOrDataBlock |
[2] |
RuleOrDataBlock |
::= | Prologue ( RuleOrData+ ( Prologue1 RuleOrData* )* )?
|
[3] |
RuleOrData |
::= | Rule | Data
|
[4] |
Prologue |
::= | Prologue1* |
[5] |
Prologue1 |
::= | BaseDecl | PrefixDecl | VersionDecl | ImportsDecl
|
[6] |
BaseDecl |
::= | 'BASE' IRIREF
|
[7] |
PrefixDecl |
::= | 'PREFIX' PNAME_NS IRIREF
|
[8] |
VersionDecl |
::= | 'VERSION' VersionSpecifier
|
[9] |
VersionSpecifier
|
::= | STRING_LITERAL1 | STRING_LITERAL2
|
[10] |
ImportsDecl |
::= | 'IMPORTS' iri
|
[11] |
Rule |
::= | 'RULE' iri? HeadTemplate 'WHERE' 'DATA'? BodyPattern
|
[12] |
Data |
::= | 'DATA' '{' DataTriplesBlock? '}'
|
[13] |
HeadTemplate |
::= | '{' HeadTemplateBlock? '}'
|
[14] |
BodyPattern |
::= | '{' BodyTriplesBlock? ( BodyNotTriples '.'? BodyTriplesBlock? )* '}'
|
[15] |
BodyNotTriples |
::= | Filter | Negation | Assignment | GroupAggregate
|
[16] |
Filter |
::= | 'FILTER' Constraint
|
[17] |
Constraint |
::= | BrackettedExpression | BuiltInCall | FunctionCall
|
[18] |
Negation |
::= | 'NOT' 'DATA'? '{' NegationPattern '}'
|
[19] |
NegationPattern |
::= | BodyTriplesBlock? ( NegationPatternNotTriples '.'? BodyTriplesBlock? )*
|
[20] |
NegationPatternNotTriples
|
::= | Filter |
[21] |
Assignment |
::= | 'SET' '(' Var ':=' Expression ')'
|
[22] |
GroupAggregate |
::= | 'GROUP' ( 'BY' ListVars )? '{' GroupPattern '}' ( ANON | '[' AggregationAssignment+ ']' )
|
[23] |
GroupPattern |
::= | BodyTriplesBlock? ( GroupPatternNotTriples '.'? BodyTriplesBlock? )*
|
[24] |
GroupPatternNotTriples
|
::= | Filter | Assignment
|
[25] |
ListVars |
::= | Var+ |
[26] |
AggregationAssignment
|
::= | Var ':=' AggregationFunction
|
[27] |
AggregationFunction
|
::= | ( 'COUNT' '(' DISTINCT? VarOrStar ')' | 'MIN' '(' Var ')' | 'MAX' '(' Var ')' | 'SUM' '(' Var ')' )
|
[28] |
VarOrStar |
::= | Var | '*'
|
[29] |
DataTriplesBlock
|
::= | TriplesSameSubjectData ( '.' DataTriplesBlock? )?
|
[30] |
TriplesSameSubjectData
|
::= | RDFTermData PropertyListNotEmptyData | TriplesNodeData PropertyListData | ReifiedTripleBlockData
|
[31] |
PropertyListData
|
::= | PropertyListNotEmptyData?
|
[32] |
PropertyListNotEmptyData
|
::= | VerbData ObjectListData ( ';' ( VerbData ObjectListData )? )*
|
[33] |
VerbData |
::= | iri | 'a'
|
[34] |
ObjectListData |
::= | ObjectData ( ',' ObjectData )*
|
[35] |
ObjectData |
::= | GraphNodeData AnnotationData
|
[36] |
GraphNodeData |
::= | RDFTermData | TriplesNodeData | ReifiedTripleData
|
[37] |
TriplesNodeData |
::= | CollectionData | BlankNodePropertyListData
|
[38] |
BlankNodePropertyListData
|
::= | '[' PropertyListNotEmptyData ']'
|
[39] |
CollectionData |
::= | '(' GraphNodeData+ ')'
|
[40] |
AnnotationData |
::= | ( ReifierData | AnnotationBlockData )*
|
[41] |
AnnotationBlockData
|
::= | '{|' PropertyListNotEmptyData '|}'
|
[42] |
ReifierData |
::= | '~' ReifierIdData?
|
[43] |
ReifierIdData |
::= | iri | BlankNode
|
[44] |
ReifiedTripleBlockData
|
::= | ReifiedTripleData PropertyListData
|
[45] |
ReifiedTripleData
|
::= | '<<' ReifiedTripleSubjectData VerbData ReifiedTripleObjectData ReifierData? '>>'
|
[46] |
ReifiedTripleSubjectData
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTripleData | TripleTermData
|
[47] |
ReifiedTripleObjectData
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTripleData | TripleTermData
|
[48] |
TripleTermData |
::= | '<<(' TripleTermSubjectData VerbData TripleTermObjectData ')>>'
|
[49] |
TripleTermSubjectData
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTermData
|
[50] |
TripleTermObjectData
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTermData
|
[51] |
HeadTemplateBlock
|
::= | TriplesBlockTemplate
|
[52] |
TriplesBlockTemplate
|
::= | TriplesSameSubjectTemplate ( '.' TriplesBlockTemplate? )?
|
[53] |
TriplesSameSubjectTemplate
|
::= | VarOrRDFTerm PropertyListNotEmptyTemplate | TriplesNodeTemplate PropertyListTemplate | ReifiedTripleBlockTemplate
|
[54] |
PropertyListTemplate
|
::= | PropertyListNotEmptyTemplate?
|
[55] |
PropertyListNotEmptyTemplate
|
::= | Verb ObjectListTemplate ( ';' ( Verb ObjectListTemplate )? )*
|
[56] |
ObjectListTemplate
|
::= | ObjectTemplate ( ',' ObjectTemplate )*
|
[57] |
ObjectTemplate |
::= | GraphNodeTemplate AnnotationTemplate
|
[58] |
GraphNodeTemplate
|
::= | VarOrRDFTerm | TriplesNodeTemplate | ReifiedTriple
|
[59] |
TriplesNodeTemplate
|
::= | CollectionTemplate | BlankNodePropertyListTemplate
|
[60] |
BlankNodePropertyListTemplate
|
::= | '[' PropertyListNotEmptyTemplate ']'
|
[61] |
CollectionTemplate
|
::= | '(' GraphNodeTemplate+ ')'
|
[62] |
AnnotationTemplate
|
::= | ( Reifier | AnnotationBlockTemplate )*
|
[63] |
AnnotationBlockTemplate
|
::= | '{|' PropertyListNotEmptyTemplate '|}'
|
[64] |
ReifiedTripleBlockTemplate
|
::= | ReifiedTriple PropertyListTemplate
|
[65] |
BodyTriplesBlock
|
::= | TriplesBlockPattern
|
[66] |
TriplesBlockPattern
|
::= | TriplesSameSubjectPattern ( '.' TriplesBlockPattern? )?
|
[67] |
ReifiedTripleBlockPattern
|
::= | ReifiedTriple PropertyListPattern
|
[68] |
TriplesSameSubjectPattern
|
::= | VarOrRDFTerm PropertyListNotEmptyPattern | TriplesNodePattern PropertyListPattern | ReifiedTripleBlockPattern
|
[69] |
PropertyListPattern
|
::= | PropertyListNotEmptyPattern?
|
[70] |
PropertyListNotEmptyPattern
|
::= | ( VerbPath | Var ) ObjectListPattern ( ';' ( ( VerbPath | Var ) ObjectListPattern )? )*
|
[71] |
ObjectListPattern
|
::= | ObjectPattern ( ',' ObjectPattern )*
|
[72] |
ObjectPattern |
::= | GraphNodePattern AnnotationPattern
|
[73] |
TriplesNodePattern
|
::= | CollectionPattern | BlankNodePropertyListPattern
|
[74] |
BlankNodePropertyListPattern
|
::= | '[' PropertyListNotEmptyPattern ']'
|
[75] |
CollectionPattern
|
::= | '(' GraphNodePattern+ ')'
|
[76] |
AnnotationPattern
|
::= | ( Reifier | AnnotationBlockPattern )*
|
[77] |
AnnotationBlockPattern
|
::= | '{|' PropertyListNotEmptyPattern '|}'
|
[78] |
GraphNodePattern
|
::= | VarOrRDFTerm | TriplesNodePattern | ReifiedTriple
|
[79] |
Reifier |
::= | '~' ReifierId?
|
[80] |
ReifierId |
::= | Var | iri | BlankNode
|
[81] |
ReifiedTriple |
::= | '<<' ReifiedTripleSubject Verb ReifiedTripleObject Reifier? '>>'
|
[82] |
ReifiedTripleSubject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
|
[83] |
ReifiedTripleObject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
|
[84] |
TripleTerm |
::= | '<<(' TripleTermSubject Verb TripleTermObject ')>>'
|
[85] |
TripleTermSubject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
|
[86] |
TripleTermObject
|
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
|
[87] |
Verb |
::= | VarOrIri | 'a'
|
[88] |
VerbPath |
::= | Path |
[89] |
Path |
::= | PathSequence |
[90] |
PathSequence |
::= | PathEltOrInverse ( '/' PathEltOrInverse )*
|
[91] |
PathEltOrInverse
|
::= | PathElt | '^' PathElt
|
[92] |
PathElt |
::= | ( iri | 'a' | '(' Path ')' )
|
[93] |
RDFTermData |
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTermData
|
[94] |
VarOrRDFTerm |
::= | Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTerm
|
[95] |
VarOrIri |
::= | Var | iri
|
[96] |
Var |
::= | VAR1 | VAR2
|
[97] |
RDFLiteral |
::= | String ( LANG_DIR | '^^' iri )?
|
[98] |
NumericLiteral |
::= | NumericLiteralUnsigned | NumericLiteralPositive | NumericLiteralNegative
|
[99] |
NumericLiteralUnsigned
|
::= | INTEGER | DECIMAL | DOUBLE
|
[100] |
NumericLiteralPositive
|
::= | INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE
|
[101] |
NumericLiteralNegative
|
::= | INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE
|
[102] |
BooleanLiteral |
::= | 'true' | 'false'
|
[103] |
String |
::= | STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2
|
[104] |
iri |
::= | IRIREF | PrefixedName
|
[105] |
PrefixedName |
::= | PNAME_LN | PNAME_NS
|
[106] |
BlankNode |
::= | BLANK_NODE_LABEL | ANON
|
[107] |
Expression |
::= | ConditionalOrExpression
|
[108] |
ConditionalOrExpression
|
::= | ConditionalAndExpression ( '||' ConditionalAndExpression )*
|
[109] |
ConditionalAndExpression
|
::= | ValueLogical ( '&&' ValueLogical )*
|
[110] |
ValueLogical |
::= | RelationalExpression
|
[111] |
RelationalExpression
|
::= | NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
|
[112] |
NumericExpression
|
::= | AdditiveExpression
|
[113] |
AdditiveExpression
|
::= | MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression | ( NumericLiteralPositive | NumericLiteralNegative ) ( ( '*' UnaryExpression ) | ( '/' UnaryExpression ) )* )*
|
[114] |
MultiplicativeExpression
|
::= | UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )*
|
[115] |
UnaryExpression |
::= | '!' PrimaryExpression
|
[116] |
PrimaryExpression
|
::= | BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
|
[117] |
FunctionCall |
::= | iri ArgList
|
[118] |
ArgList |
::= | NIL | '(' Expression ( ',' Expression )* ')'
|
[119] |
ExpressionList |
::= | NIL | '(' Expression ( ',' Expression )* ')'
|
[120] |
iriOrFunction |
::= | iri ArgList?
|
[121] |
ExprTripleTerm |
::= | '<<(' ExprTripleTermSubject Verb ExprTripleTermObject ')>>'
|
[122] |
ExprTripleTermSubject
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var
|
[123] |
ExprTripleTermObject
|
::= | iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
|
[124] |
BrackettedExpression
|
::= | '(' Expression ')'
|
[125] |
BuiltInCall |
::= | 'STR' '(' Expression ')'
|
터미널 생성 규칙:
[126] |
IRIREF |
::= | '<' ([^<>"{}|^`\]-[#x00-#x20] | UCHAR )* '>'
|
[127] |
PNAME_NS |
::= | PN_PREFIX? ':' |
[128] |
PNAME_LN |
::= | PNAME_NS PN_LOCAL
|
[129] |
BLANK_NODE_LABEL
|
::= | '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?
|
[130] |
VAR1 |
::= | '?' VARNAME |
[131] |
VAR2 |
::= | '$' VARNAME |
[132] |
LANG_DIR |
::= | '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ('--' [a-zA-Z]+)?
|
[133] |
INTEGER |
::= | [0-9]+ |
[134] |
DECIMAL |
::= | [0-9]* '.' [0-9]+ |
[135] |
DOUBLE |
::= | ( ([0-9]+ ('.'[0-9]*)? ) | ( '.' ([0-9])+ ) ) [eE][+-]?[0-9]+
|
[136] |
INTEGER_POSITIVE
|
::= | '+' INTEGER
|
[137] |
DECIMAL_POSITIVE
|
::= | '+' DECIMAL
|
[138] |
DOUBLE_POSITIVE |
::= | '+' DOUBLE
|
[139] |
INTEGER_NEGATIVE
|
::= | '-' INTEGER
|
[140] |
DECIMAL_NEGATIVE
|
::= | '-' DECIMAL
|
[141] |
DOUBLE_NEGATIVE |
::= | '-' DOUBLE
|
[142] |
STRING_LITERAL1 |
::= | "'" ( ([^#x27#x5C#xA#xD]) | ECHAR | UCHAR )* "'"
|
[143] |
STRING_LITERAL2 |
::= | '"' ( ([^#x22#x5C#xA#xD]) | ECHAR | UCHAR )* '"'
|
[144] |
STRING_LITERAL_LONG1
|
::= | "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR | UCHAR ) )* "'''"
|
[145] |
STRING_LITERAL_LONG2
|
::= | '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR | UCHAR ) )* '"""'
|
[146] |
ECHAR |
::= | '\' [tbnrf\"'] |
[147] |
UCHAR |
::= | ('\u' HEX HEX HEX HEX) | ('\U' HEX HEX HEX HEX HEX HEX HEX HEX)
|
[148] |
NIL |
::= | '(' WS* ')' |
[149] |
WS |
::= | #x20 | #x9 | #xD | #xA |
[150] |
ANON |
::= | '[' WS* ']' |
[151] |
PN_CHARS_BASE |
::= | [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
|
[152] |
PN_CHARS_U |
::= | PN_CHARS_BASE | '_'
|
[153] |
VARNAME |
::= | ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )*
|
[154] |
PN_CHARS |
::= | PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
|
[155] |
PN_PREFIX |
::= | PN_CHARS_BASE ((PN_CHARS|'.')* PN_CHARS)?
|
[156] |
PN_LOCAL |
::= | (PN_CHARS_U | ':' | [0-9] | PLX ) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX) )?
|
[157] |
PLX |
::= | PERCENT | PN_LOCAL_ESC
|
[158] |
PERCENT |
::= | '%' HEX HEX
|
[159] |
HEX |
::= | [0-9] | [A-F] | [a-f] |
[160] |
PN_LOCAL_ESC |
::= | '\' ( '_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=' | '/' | '?' | '#' | '@' | '%' )
|
이 문법의 텍스트 버전은 다음 파일에서 확인할 수 있습니다:
sparql-rl-grammar.bnf.
이 문서에서는 일부 터미널 리터럴 문자열을 사용합니다. [EBNF-NOTATION]. 이러한 문자열에 사용된 유니코드 코드 포인트를 명확히 하기 위해 다음 표에서는 해당 터미널 리터럴 문자열에 사용된 구체적인 문자를 설명합니다.
| 코드 | 글리프 | 설명 |
|---|---|---|
U+000A |
LF |
줄 바꿈 |
U+000D |
CR |
캐리지 리턴 |
U+0023 |
# |
숫자 기호 |
U+0025 |
% |
퍼센트 기호 |
U+005C |
\ |
백슬래시 |
이 절은 규범적이지 않습니다.
다음 알고리즘은 참조된 모든 문서를 재귀적으로 방문하여
IMPORTS 문을 해석하는 한 가지 방법을 보여 줍니다.
두 규칙 집합 RS1과 RS2의 규칙 집합 병합은
다음과 같이 정의되는 규칙 집합 MR을 생성합니다.
let RS be a rule set
let V = {}
if RS has a location:
V = { location of RS }
endif
define ruleSetMerge(rule set RS1, rule set RS2):
let MR be a rule set
MR.rules = RS1.rules ∪ RS2.rules
MR.data = rdf_merge(RS1.data, RS2.data)
MR.imports = {}
the result is MR
enddefine
define imports(rule set RS):
let RS2 be a rule set formed from RS.rules and RS.data
foreach URL x in RS.imports:
if x ∉ V:
V = V ∪ { x }
read rule set RS3 from URL x
RS2 = ruleSetMerge(RS2, imports(RS3))
endif
endfor
the result is RS2
enddefine
result is imports(RS)
여기서 rdf_merge는
RDF
병합
연산입니다.
SPARQL-RL의 인터넷 미디어 유형(이전에는 MIME 유형이라고 함)은
"application/sparql-rl"입니다.
다음 정보는 검토, 승인 및 IANA 등록을 위해 인터넷 엔지니어링 운영 그룹(IESG)에 제출되었습니다.
이 절은 규범적이지 않습니다.
SPARQL-RL 문서에는 IMPORTS 문이 포함될 수 있습니다. 이 문은 다른
SPARQL-RL 문서를 참조하고 그 내용을 현재
문서로 가져옵니다.
가져온 문서 자체에 IMPORTS 문이 포함되어 있으면,
해당 문서들도 가져옵니다.
규칙
집합을 모듈화하는 데 유용하지만, IMPORTS 문을 사용하면
보안 위험이 발생할 수 있습니다.
위험에는 다음과 같은 경우가 포함되지만, 이에 국한되지는 않습니다. 규칙 집합이
평가 중 악의적으로든 우발적으로든 과도한 연산을 유발하는 경우,
HTTP 요청이 가로채어져 다른 문서가 반환되는 경우가 있으며,
여기에는 오래된 사본이 반환되는 경우도 포함됩니다.
SPARQL-RL 규칙 집합을 RDF 그래프에 적용하면 상당한 연산과 메모리 사용이 발생할 수 있으며, 이를 악용하여 서비스 거부를 유발할 수 있습니다. 애플리케이션은 SPARQL-RL 규칙 집합을 적용할 때 발생할 수 있는 연산량과 메모리 사용량을 제한하도록 주의해야 합니다.
SPARQL-RL 구문은 UTF-8 [RFC3629]로 인코딩되며, 문자열 데이터에서 이스케이프하지 않은 제어 문자의 사용을 허용합니다. 이 명세는 이러한 내용을 최종 사용자에게 직접 노출하지 않지만, 사용자 에이전트를 통해 표시될 수 있으며, 이러한 문자로 인해 표시된 텍스트가 오해를 일으킬 수 있습니다.
SPARQL-RL은 임의의 애플리케이션 데이터를 처리하고 생성하는 데 사용할 수 있으며, 보안 고려 사항은 사용 분야에 따라 달라집니다. 텍스트에 적용할 수 있는 보안 도구와 프로토콜 (예: PGP 암호화, 체크섬 검증, 비밀번호로 보호된 압축)은 SPARQL-RL 문서에도 사용할 수 있습니다. SPARQL-RL 규칙 집합 평가 결과에 포함된 정보의 민감도를 반영하도록 보안/개인정보 보호 프로토콜을 적용해야 합니다.
SPARQL-RL의 보안 고려 사항에는 다음에 대한 보안 고려 사항도 포함됩니다: RDF 데이터 및 다음과 같은 형식: RDF Turtle.
이 절은 규범적이지 않습니다.
SPARQL-RL 문서에는 추가적인 애플리케이션 데이터가 포함될 수 있으며, 여기에는 개인 식별 정보(PII)를 표현한 내용이나 민감한 것으로 간주될 수 있는 기타 정보가 포함될 수 있습니다. 이러한 정보가 포함된 규칙 집합을 게시하는 작성자는 해당 정보를 게시할 필요성과 용도를 신중하게 고려하고, 데이터가 사용되거나 잠재적으로 공개될 것으로 예상되는 지역에 적용되는 규정(예: GDPR, CCPA, 기타 규정)도 고려해야 하며, 특히 데이터 접근에 승인 조치가 필요한지 검토하는 것이 좋습니다.
이 절은 규범적이지 않습니다.
다음 분들은 Data Shapes 작업 그룹의 규칙 태스크 포스에서 SPARQL-RL 개발에 기여했습니다: Robert David, David Habgood, Livio Robaldo, Ognjen Savkovic, Andy Seaborne, Simon Steyskal 및 Ted Thibodeau Jr.
Data Shapes 워킹 그룹의 구성원에는 @@가 포함되었습니다.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: