Я устал смотреть на, возможно, самый уродливый оператор SQL, который я когда-либо создавал и нуждался в вашей помощи. Я просматриваю XML-документ для различных элементов и хочу видеть их XPath. Нижеприведенный запрос работает с помощью грубой силы, но я не могу создать способ создания функции или CTE, который будет правильно поддерживать N уровней.Как рекурсивно получить XPath узла с использованием SQL Server?
declare @article xml = '<article>
<front>
<article-meta>
<title-group>
<article-title>Update on ...</article-title>
</title-group>
</article-meta>
</front>
<back>
<ref-list>
<ref id="R1">
<citation citation-type="journal">
<article-title>Retrospective study of ...</article-title>
</citation>
</ref>
</ref-list>
</back>
</article>'
SELECT
Cast(T.r.query('local-name(parent::*/parent::*/parent::*/parent::*/parent::*/parent::*)') AS varchar(max)) + '/' +
Cast(T.r.query('local-name(parent::*/parent::*/parent::*/parent::*/parent::*)') AS varchar(max)) + '/' +
Cast(T.r.query('local-name(parent::*/parent::*/parent::*/parent::*)') AS varchar(max)) + '/' +
Cast(T.r.query('local-name(parent::*/parent::*/parent::*)') AS varchar(max)) + '/' +
Cast(T.r.query('local-name(parent::*/parent::*)') AS varchar(max)) + '/' +
Cast(T.r.query('local-name(parent::*)') AS varchar(max)) AS ThePath,
Cast(T.r.query('local-name(.)') AS varchar(max)) AS TheElement,
T.r.query('.') AS TheXml
FROM @article.nodes('//article-title') T(r)
Результат:
ThePath TheElement
//article/front/article-meta/title-group article-title
/article/back/ref-list/ref/citation article-title
То, что я действительно хочу:
SELECT
x.RowId,
dbo.GetXPath(T.r.query('.')) AS ThePath, -- <---- Magic function goes here
T.r.query('.') AS TheXml
FROM dbo.InputFormatXml x
JOIN dbo.InputFormat f
ON F.InputFormatId = x.InputFormatId
CROSS APPLY TheData.nodes('//article-title') T(r)
WHERE F.Description = 'NLM';
Спасибо. Это хорошо работает для упрощенного сценария, который я изначально перечислял. Я упомянул о создании функции или CTE, поэтому я мог бы использовать ее в «реальном» сценарии, где я собираю тысячи элементов на основе оператора XPath и запуская запрос, который будет производить все родительские узлы, занимает несколько часов, что не является разумным. Как я могу параметризовать запрос «SELECT @article AS node» без необходимости предоставления полного набора данных из тысяч статей? – kratka