अपडेट करें:
मैंने कोड को अपडेट किया है, साथ ही इनपुट और आउटपुट एक्सएमएल में उदाहरण क्वेरी में नवीनतम आवश्यकता को प्रतिबिंबित करने के लिए नीचे, @ मिकेल के ठीक उत्तर पर एक टिप्पणी में कहा गया है , जो है:
@Value रिक्त है या मौजूद नहीं है, तो मान तत्व बनाने के लिए नहीं
हालांकि एक एकल अभिव्यक्ति इस नई भिन्नता को सही ढंग से मेल कर सकती है, लेकिन <Value/>
एकल पास में खाली तत्व को छोड़ने का एक तरीका नहीं दिखता है क्योंकि प्रतिस्थापन स्ट्रिंग में सशर्त तर्क की अनुमति नहीं है। इसलिए, मैंने इसे 2 भाग संशोधन के लिए अनुकूलित किया है: एक पास गैर-खाली @Value
विशेषताओं को प्राप्त करने के लिए और एक पास खाली @Value
विशेषताओं को प्राप्त करने के लिए । वैसे भी तत्व नहीं <Element>
होने के @Value
कारण विशेषता को याद रखने की कोई आवश्यकता नहीं थी <Value>
।
एक विकल्प XML को एक नियमित स्ट्रिंग के रूप में मानने और इसे एक पैटर्न के आधार पर बदलने का है। यह नियमित एक्सप्रेशन (विशेष रूप से "बदलें" फ़ंक्शन) का उपयोग करके आसानी से पूरा किया जाता है, जिसे SQLCLR कोड के माध्यम से उपलब्ध कराया जा सकता है।
नीचे दिया गया उदाहरण SQL # लाइब्रेरी से RegEx_Replace स्केलर UDF का उपयोग करता है (जो मैं इसका लेखक हूं, लेकिन यह RegEx फ़ंक्शन नि: शुल्क संस्करण में उपलब्ध है, साथ ही कई अन्य):
DECLARE @SomeXml XML;
SET @SomeXml = N'<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra1" />
<Element Code="22" Value="bbb" ExtraData="extra2" />
<Element Code="333" Value="ccc" ExtraData="extra3" />
<Element Code="4444" Value="" ExtraData="extra4" />
<Element Code="55555" ExtraData="extra5" />
</Elements>
<ExtraData>
<Something Val="1">qwerty A</Something>
<Something Val="2">qwerty B</Something>
</ExtraData>
</Root>';
DECLARE @TempStringOfXml NVARCHAR(MAX),
@Expression NVARCHAR(4000),
@Replacement NVARCHAR(4000);
SET @TempStringOfXml = CONVERT(NVARCHAR(MAX), @SomeXml);
PRINT N'Original: ' + @TempStringOfXml;
---
SET @Expression =
N'(<Element Code="[^"]+")\s+Value="([^"]+)"\s+(ExtraData="[^"]+")\s*/>';
SET @Replacement = N'$1 $3><Value>$2</Value></Element>';
SELECT @TempStringOfXml = SQL#.RegEx_Replace(@TempStringOfXml, @Expression,
@Replacement, -1, 1, '');
PRINT '-------------------------------------';
PRINT N'Phase 1: ' + @TempStringOfXml; -- transform Elements with a non-empty @Value
---
SET @Expression = N'(<Element Code="[^"]+")\s+Value=""\s+(ExtraData="[^"]+")\s*/>';
SET @Replacement = N'$1 $2 />';
SELECT @TempStringOfXml = SQL#.RegEx_Replace(@TempStringOfXml, @Expression,
@Replacement, -1, 1, '');
PRINT '-------------------------------------';
PRINT N'Phase 2: ' + @TempStringOfXml; -- transform Elements with an empty @Value
SELECT CONVERT(XML, @TempStringOfXml); -- prove that this is valid XML
PRINT
बयान सिर्फ "संदेश" टैब में तुलना करने में आसानी साइड-बाई-साइड के लिए बनाने के लिए कर रहे हैं। परिणामी आउटपुट है (मैंने मूल XML को थोड़ा संशोधित किया ताकि यह स्पष्ट हो सके कि केवल वांछित भागों को छुआ गया था और कुछ नहीं):
Original: <Root attr1="val1" attr2="val2"><Elements><Element Code="1" Value="aaa" ExtraData="extra1"/><Element Code="22" Value="bbb" ExtraData="extra2"/><Element Code="333" Value="ccc" ExtraData="extra3"/><Element Code="4444" Value="" ExtraData="extra4"/><Element Code="55555" ExtraData="extra5"/></Elements><ExtraData><Something Val="1">qwerty A</Something><Something Val="2">qwerty B</Something></ExtraData></Root>
-------------------------------------
Phase 1: <Root attr1="val1" attr2="val2"><Elements><Element Code="1" ExtraData="extra1"><Value>aaa</Value></Element><Element Code="22" ExtraData="extra2"><Value>bbb</Value></Element><Element Code="333" ExtraData="extra3"><Value>ccc</Value></Element><Element Code="4444" Value="" ExtraData="extra4"/><Element Code="55555" ExtraData="extra5"/></Elements><ExtraData><Something Val="1">qwerty A</Something><Something Val="2">qwerty B</Something></ExtraData></Root>
-------------------------------------
Phase 2: <Root attr1="val1" attr2="val2"><Elements><Element Code="1" ExtraData="extra1"><Value>aaa</Value></Element><Element Code="22" ExtraData="extra2"><Value>bbb</Value></Element><Element Code="333" ExtraData="extra3"><Value>ccc</Value></Element><Element Code="4444" ExtraData="extra4" /><Element Code="55555" ExtraData="extra5"/></Elements><ExtraData><Something Val="1">qwerty A</Something><Something Val="2">qwerty B</Something></ExtraData></Root>
यदि आप किसी तालिका में किसी फ़ील्ड को अपडेट करना चाहते हैं, तो आप निम्नलिखित होने के लिए उपरोक्त को अनुकूलित कर सकते हैं:
DECLARE @NonEmptyValueExpression NVARCHAR(4000),
@NonEmptyValueReplacement NVARCHAR(4000),
@EmptyValueExpression NVARCHAR(4000),
@EmptyValueReplacement NVARCHAR(4000);
SET @NonEmptyValueExpression =
N'(<Element Code="[^"]+")\s+Value="([^"]+)"\s+(ExtraData="[^"]+")\s*/>';
SET @NonEmptyValueReplacement = N'$1 $3><Value>$2</Value></Element>';
SET @EmptyValueExpression =
N'(<Element Code="[^"]+")\s+Value=""\s+(ExtraData="[^"]+")\s*/>';
SET @EmptyValueReplacement = N'$1 $2 />';
UPDATE tbl
SET XmlField = SQL#.RegEx_Replace4k(
SQL#.RegEx_Replace4k(
CONVERT(NVARCHAR(4000), tbl.XmlField),
@NonEmptyValueExpression,
@NonEmptyValueReplacement,
-1, 1, ''),
@EmptyValueExpression,
@EmptyValueReplacement,
-1, 1, '')
FROM SchemaName.TableName tbl
WHERE tbl.XmlField.exist('Root/Elements/Element/@Value') = 1;
<Value>
प्रत्येक पर कई तत्व रखने की योजना नहीं बनाते हैं, तब तक मैं इसके किसी भी लाभ के बारे में नहीं सोच सकता<Element>
। यदि नहीं, तो विशेषता को एक तत्व में ले जाना अधिक फूला हुआ, और संभवतः कम कुशल, एक्सएमएल के लिए बनाता है।