T-SQL метод xquery .modify с использованием подстановочного знака

Я работаю в SQL Server 2014. Я создал хранимую процедуру, которая выполняет ее обработку, и в конце принимает окончательный вывод запроса и форматирует его как XML. Из-за природы логики в процедуре, иногда узел должен быть удален из окончательного XML-вывода. Вот пример вывода XML (для краткости я не включил корневые узлы; надеюсь, они не потребуются для ответа на мой вопрос):

<DALink>
    <InteractingIngredients>
        <InteractingIngredient>
            <IngredientID>1156</IngredientID>
            <IngredientDesc>Lactobacillus acidophilus</IngredientDesc>
            <HICRoot>Lactobacillus acidophilus</HICRoot>
            <PotentiallyInactive>Not necessary</PotentiallyInactive>
            <StatusCode>Live</StatusCode>
        </InteractingIngredient>
    </InteractingIngredients>
    <ActiveProductsExistenceCode>Exist</ActiveProductsExistenceCode>
    <IngredientTypeBasisCode>1</IngredientTypeBasisCode>
    <AllergenMatch>Lactobacillus acidophilus</AllergenMatch>
    <AllergenMatchType>Ingredient</AllergenMatchType>
</DALink>
<ScreenDrug>
    <DrugID>1112894</DrugID>
    <DrugConceptType>RxNorm_SemanticClinicalDr</DrugConceptType>
    <DrugDesc>RxNorm LACTOBACILLUS ACIDOPHILUS/PECTIN ORAL capsule</DrugDesc>
    <Prospective>true</Prospective>
</ScreenDrug>

В этой процедуре у меня есть код, который просматривает структуру XML выше и удаляет узел, когда его там не должно быть, потому что легче изменить XML, чем настроить вывод запроса. Вот пример этого кода:

SET @xml_Out.modify('declare namespace ccxsd="http://schemas.foobar.com/CC/v1_3"; delete //ccxsd:InteractingIngredients[../../../ccxsd:ScreenDrug/ccxsd:DrugConceptType="OneThing"]');
SET @xml_Out.modify('declare namespace ccxsd="http://schemas.foobar.com/CC/v1_3"; delete //ccxsd:InteractingIngredients[../../../ccxsd:ScreenDrug/ccxsd:DrugConceptType="AnotherThing"]');
SET @xml_Out.modify('declare namespace ccxsd="http://schemas.foobar.com/CC/v1_3"; delete //ccxsd:InteractingIngredients[../../../ccxsd:ScreenDrug/ccxsd:DrugConceptType="SomethingElse"]');
SET @xml_Out.modify('declare namespace ccxsd="http://schemas.foobar.com/CC/v1_3"; delete //ccxsd:InteractingIngredients[../../../ccxsd:ScreenDrug/ccxsd:DrugConceptType="SomethingElseAgain"]');
SET @xml_Out.modify('declare namespace ccxsd="http://schemas.foobar.com/CC/v1_3"; delete //ccxsd:InteractingIngredients[../../../ccxsd:ScreenDrug/ccxsd:DrugConceptType="RxNorm*"]');

Последняя команда, которую я не могу понять, как заставить работать. Все, что мне нужно сделать, - это искать случаи, когда элемент "DrugConceptType" начинается со строки "RxNorm", поскольку существует несколько версий строки, которые могут возникнуть.

У меня есть Googled и StackOverFlowed, но, возможно, из-за моей неопытности в этой области я не правильно задал вопрос.

Есть ли относительно простой способ переписать последний оператор.modify выше, чтобы использовать подстановочный знак после "RxNorm"?

1 ответ

Решение

Ваше сокращение корневого узла является проблемой на самом деле, так как вы используете пространство имен "ccxsd", а ваш XML не показывает этого.

Во всяком случае, лучше, чем написать declare namespace ... снова и снова, это было первой строкой вашего заявления:

;WITH XMLNAMESPACES('http://schemas.fdbhealth.com/CC/v1_3' AS ccxsd)

Ну как .modify() это вызов одного оператора, это не имеет такого значения...

Но на ваш вопрос о подстановочных

Это удалит все узлы, где содержимое элемента начинается с "RxNorm":

SET @xml.modify('delete //*[fn:substring(.,1,6)="RxNorm"]');

Помните о пропущенных пространствах имен... Не могу проверить это...

РЕДАКТИРОВАТЬ: упрощенный рабочий пример:

Вы должны проверить это с вашим фактическим XML (с корнем и пространством имен)

DECLARE @xml_Out XML=
'<DALink>
    <InteractingIngredients>
        <InteractingIngredient>
            <IngredientID>1156</IngredientID>
            <IngredientDesc>Lactobacillus acidophilus</IngredientDesc>
            <HICRoot>Lactobacillus acidophilus</HICRoot>
            <PotentiallyInactive>Not necessary</PotentiallyInactive>
            <StatusCode>Live</StatusCode>
        </InteractingIngredient>
    </InteractingIngredients>
    <ActiveProductsExistenceCode>Exist</ActiveProductsExistenceCode>
    <IngredientTypeBasisCode>1</IngredientTypeBasisCode>
    <AllergenMatch>Lactobacillus acidophilus</AllergenMatch>
    <AllergenMatchType>Ingredient</AllergenMatchType>
</DALink>
<ScreenDrug>
    <DrugID>1112894</DrugID>
    <DrugConceptType>RxNorm_SemanticClinicalDr</DrugConceptType>
    <DrugDesc>RxNorm LACTOBACILLUS ACIDOPHILUS/PECTIN ORAL capsule</DrugDesc>
    <Prospective>true</Prospective>
</ScreenDrug>';

SET @xml_Out.modify('delete //InteractingIngredients[fn:substring((../../ScreenDrug/DrugConceptType)[1],1,6)="RxNorm"]');

SELECT @xml_Out;
Другие вопросы по тегам