2012-09-13 16 views
5

होना चाहिए मैंने SO: XML data type method “value” must be a string literal के माध्यम से पढ़ा है लेकिन मेरी समस्या थोड़ा अलग है। मेरे पास एक चर में xml का थोड़ा सा हिस्सा है जिसे मैं अलग करना चाहता हूं और मुझे पथ दिया गया है। मूल रूप से मैंने यह कोशिश की:XML डेटा प्रकार विधि "मान" का तर्क 1 स्ट्रिंग अक्षर

declare @x xml 
select @x = '....' 
select @x.value('(' + @path + ')[1]', 'varchar(max)') 

लेकिन, ज़ाहिर है, यह विफल रहता है। तो मैं एसक्यूएल पाया: चर और इस की कोशिश की:

select @x.value('(sql:variable("@path"))[1]', 'varchar(max)') 

लेकिन यह दिलचस्प @path का मान देता है (क्यों?)। मैं इसके साथ गड़बड़ कर रहा हूं लेकिन यह सही काम करने के लिए नहीं मिल सकता है।

विचार किसी को भी?

+0

कृपया वास्तविक SO URL का उपयोग करें। आप किसी भी प्रश्न या उत्तर के नीचे 'शेयर' लिंक पर राइट-क्लिक कर सकते हैं और 'कॉपी' चुन सकते हैं, और यह शीर्षक से सही ढंग से लिंक किया जाएगा (जैसा कि मैंने उपरोक्त आपके यूआरएल में किया था)। धन्यवाद। –

उत्तर

2

माइक्रोसॉफ्ट साइट पर wBob से मदद के साथ, अब मुझे एक साफ समाधान मिला है। प्रदर्शन, ज़ाहिर है, पूरे दस्तावेज़ के रूप में एक चिंता का विषय एक एकल पथ के लिए मैप किया गया है जाएगा मिल लेकिन सुधार पाठक :)

if object_id('VMConfigVal') is not null 
drop function VMConfigVal 
go 
create function VMConfigVal(@x xml, @path varchar(max)) 
returns nvarchar(max) 
as 
begin 
    declare @ret nvarchar(max) 

    ;with cte as 
    (
    select value = x.c.value('.', 'varchar(50)') 
    ,  path = cast (null as varchar(max)) 
    ,  node = x.c.query('.') 
    from @x.nodes('/*') x(c) 
    union all 
    select n.c.value('.', 'varchar(50)') 
    ,  isnull(c.path + '/', '/') 
     +  n.c.value('local-name(.)', 'varchar(max)') 
    ,  n.c.query('*') 
    from cte c 
    cross apply c.node.nodes('*') n(c) 
    ) 
    select @ret = value from cte where path = @path 
    return @ret 
    end 
go 

इसलिए मैं अब कुछ की तरह कर सकते हैं के लिए सुझाव संभावनाओं के रूप में छोड़ दिया जाता है:

select dbo.VMConfigVal(MyXMLConfig, '/hardware/devices/IDE/ChannelCount') 
from someTable 

मीठा!

3

आपका चयन @path का मान देता है क्योंकि sql:variable() एक शाब्दिक मूल्य देता है, इसलिए असल में आप दस्तावेज़ से शाब्दिक मान @path का चयन करने के लिए SQL सर्वर से पूछ रहे हैं। एक ही रास्ता मैं ऐसा करने का पता है कि तुम क्या चाहते हैं, गतिशील एसक्यूएल का उपयोग कर दिया जाएगा ताकि तरह:

declare @xml xml = ' 
<root> 
    <element attr="test">blah</element> 
</root>'; 

declare @p nvarchar(max) = '(//element/text())[1]'; 
declare @sql nvarchar(max) 
    = 'select @x.value(''' + @p + ''', ''nvarchar(max)'')'; 

exec sp_executesql @sql, @parameters = N'@x xml', @x = @xml; 

लेकिन मैं आपको चेतावनी देता चाहिए कि यह बहुत अच्छा अभ्यास नहीं है (एसक्यूएल इंजेक्शन, मान्य इनपुट, आदि के बारे में सोचने)

+0

मैं भाग्य से बाहर हूं क्योंकि मैं इसे यूडीएफ के भीतर करने की कोशिश कर रहा हूं। grrr ... (धन्यवाद) – ekkis

+0

हम्म ... वैकल्पिक रूप से, मैं कुछ// my/path/mytag [@ someattr = sql: variable ("@ myattr")] '... जैसे कुछ कर सकता हूं क्वेरी में एक विशेषता की तलाश करने के बजाय एक दिया गया पथ/टैग ढूंढता है? – ekkis

+0

आप यह कर सकते हैं: '@ xml.value (' (// * [स्थानीय-नाम() = sql: variable ("@ elementname")] चुनें [)], 'nvarchar (max)') ', '@elementname = 'element'' के साथ। शायद कुछ हैकिंग के साथ आप इसे पथ से देखने के लिए प्राप्त कर सकते हैं, लेकिन मैं आपको अधिक जानकारी के बिना निश्चित रूप से नहीं बता सकता। –

1

आप केवल नाम से चाइल्ड तत्व खोजने के लिए और XPath शाब्दिक यहां से सार नाम देना चाहते हैं की जरूरत है कुछ विकल्प हैं:

// Returns the /root/node/element/@Value with @Name contained in @AttributeName SQL variable. 
SELECT @Xml.value('(/root/node/element[@Name=sql:variable("@AttributeName")]/@Value)[1]', 'varchar(100)') 

// Returns the text of the child element of /root/node with the name contained in @ElementName SQL variable. 
SELECT @Xml.value('(/root/node/*[name(.)=sql:variable("@ElementName")]/text())[1]', 'varchar(100)') 

// Searching the xml hierarchy for elements with the name contained in @ElementName and returning the text(). 
SELECT @Xml.value('(//*[name(.)=sql:variable("@ElementName")]/text())[1]', 'varchar(100)') 

आप को चलाने के लिए @ElementName या @AttributeName एसक्यूएल चर घोषित करने के लिए की जरूरत है इन। मैंने पहले बयान का परीक्षण किया, लेकिन एफआईआई के अन्य 2 बयानों का स्पष्ट रूप से परीक्षण नहीं किया है।

+0

लेकिन बिंदु यह था कि मैं – ekkis

+0

तत्व के पथ को हार्ड-कोड नहीं करना चाहता था, दूसरे नाम में सुझाए गए प्रारूप का उपयोग करके नाम (।) से स्थानीय नाम() के साथ मुझे बेहतर भाग्य मिला। यह प्रारूप क्रॉस लागू करने के मुकाबले एक बहुत अच्छा अच्छा और साफ है, यह निश्चित रूप से है। – edhubbell

संबंधित मुद्दे