How can I declare the namespaces in a query?
I get an error when declaring the namespaces
Declare #Mydoc xml
set #Mydoc = (
select importe, algo,XD,
(select impuesto,tasa,transferencia
from CfdiDet
for xml raw('cfdi_detalle'),type)
from cfdienc
for xml raw('cfdi_encabezado'),type)
This is the part where I have a problem
set #Mydoc.modify('declare xmlnamespaces ('uri',cfdi')
I want to replace the "_" with ":"
The namespace prefixes are not just a part of string you could manipulate with a .modify()... Well, you could convert the XML to string, do a REPLACE and convert it back to XML. But the proper way is to declare the namespace.
To declare a namespace you can either use WITH XMLNAMESPACES or use an implicit namespace declaration (not possible in your case).
Try this
DECLARE #Mydoc XML;
WITH XMLNAMESPACES('uri' AS cfdi)
SELECT #Mydoc=
(
SELECT 'SomeDummy' AS importe
FOR XML RAW('cfdi:encabezado'),TYPE
);
SELECT #Mydoc
The result
<cfdi:encabezado xmlns:cfdi="uri" importe="SomeDummy" />
Related
Need to get the list of xml present inside an xml. This is what I have tried.
DECLARE #xml xml
SET #xml = '<a><b /><c><d /><d /><d /></c></a>';
DECLARE #i_xml xml = #xml.value('(/a/b/c)[1]', 'VARCHAR(100)')
Select #i_xml
But this gives me NULL
Based on your sample xml, c and b are on same child record of <a>. value() will give a scalar result, use query() instead.
DECLARE #xml xml
SET #xml = '<a><b /><c><d /><d /><d /></c></a>';
DECLARE #i_xml xml = #xml.query('(//a/c/child::*)')
SELECT #i_xml
I need to use a dynamic string for an xquery path but .query/.nodes methods require a literal string as parameter. So I decided to try sql:variable
DECLARE #xmlData XML, #node varchar(max)
SET #xmlData = 'Some XML Here'
SET #node = '/path1/path2/path3'
When I query with
select #xmlData.query('/path1/path2/path3')
It returns the intended result
But when I query with
select #xmlData.query('sql:variable("#node")')
It returns the variable value itself as "/path1/path2/path3"
What is wrong here?
This should do the trick:
select #xmlData.query('/*[local-name()=sql:variable("#node")]')
It matches any node with a wildcard *, but there is an extra predicate that the name has to match the variable
For performance reasons, you should preferably use /text() to get inner text, and use .values to get a single value.
select #xmlData.value('(/*[local-name()=sql:variable("#node")]/text())[1]', 'nvarchar(100)')
sql:variable is used to substitute a single scalar variable into an XPath expression, so can't be used to define a full path. You can use it to test against a single node's name, though, e.g.:
declare #xmlData XML = '<path1><path2><path3>foo</path3></path2></path1>'
select [example1] = #xmlData.query('/path1/path2/path3')
--example1
--<path3>foo</path3>
declare #node1 varchar(max) = 'path1'
declare #node2 varchar(max) = 'path2'
declare #node3 varchar(max) = 'path3'
select [example2] = #xmlData.query('//*[local-name()= sql:variable("#node1")]/*[local-name()= sql:variable("#node2")]/*[local-name()= sql:variable("#node3")]');
--example2
--<path3>foo</path3>
I wants to separate string by comma. Actually I wants to filter in WHERE Clause like
CREATE PROC spGetRecords
#class varchar(50)
AS
BEGIN
SELECT *
FROM SampleTable
WHERE class in (#class) --in Database class is an integer
END
So, I want to pass the parameter when execute query like below
spGetRecords #class = '12,22,45,66'
I think it's not possible to pass multiple value in single parameter in my case.
So, If I remove separate the string by ',' then I can run my query in while loop that will bring the record correct?
So, How can I separate the string by comma
You can try splitting using xml path as below:
Declare #delimiter nvarchar(max) = ','
Declare #str nvarchar(max) = '12,22,45,66'
Declare #xml as xml
Select #xml = CAST('<x>' + REPLACE((SELECT REPLACE(#str,#delimiter,'$$$SSText$$$') AS [*] FOR XML PATH('')),'$$$SSText$$$','</x><x>')+ '</x>' AS XML)
--select #xml
Select y.value(N'text()[1]', N'nvarchar(MAX)') as value
FROM #xml.nodes(N'x') as x(y)
If you are in SQL Server >= 2016 you can use STRING_SPLIT() as below:
Select * from string_split('12,22,45,66',',')
Use dynamic SQL
exec 'SELECT * FROM SampleTable WHERE class in (' + #class + ')'
which will patch the strings together and then execute it like this:
SELECT * FROM SampleTable WHERE class in (12,22,45,66)
Here is a good solution - Converting String List into Int List in SQL . Idea here is to send in an int list to a stored procedure as an XML parameter.
Here is another quick but dirty solution - t-sql Convert comma separated string into int, without using user created function . Here the passed in value is used within a dynamic sql statement.
More ideas - http://sql-articles.com/scripts/function-to-split-comma-separated-string-to-integer/
I have a simple XML List, which looks like this:
<i>8</i>
<i>20</i>
<i>24</i>
For this example I want to remove the 2nd Node from this List.
How do I do that?
DECLARE #xml XML;
SET #xml = <i>8</i><i>20</i><i>24</i>
SELECT #xml.modify('delete <i>20</i>')
Thank you!
Removes nodes from the xml where text equals value of 20:
DECLARE #xml XML = '<i>8</i><i>20</i><i>24</i>';
SET #xml.modify('delete i[text()="20"]')
select #xml;
Removes the 2nd "i" node in the XML:
DECLARE #xml XML = '<i>8</i><i>20</i><i>24</i>';
SET #xml.modify('delete i[2]')
select #xml;
Bonus: Removes nodes from the xml where text contains a value of 20:
DECLARE #xml XML = '<i>8</i><i>20 </i><i>24</i>';
SET #xml.modify('delete i[text()][contains(.,"20")]')
select #xml;
Try it like this
DECLARE #xml XML;
SET #xml = N'<i>8</i><i>20</i><i>24</i>';
DECLARE #pos INT=2;
SET #xml.modify('delete /i[sql:variable("#pos")][1]');
SELECT #xml;
I'm working on a problem even my colleagues say is impossible. There is XML already in our database and I want to be able to take single attributes from the XML and set them equal to variables to work with. This is my code so far (that doesn't work).
declare #MyText varchar(10)
declare #MyXML XML
set #MyXML = '
<ns0:TestXML xmlns:ns0="http://test.com">
<TestValue>11</TestValue>
</ns0:TestXML>'
set #MyText =
(
;with XMLNAMESPACES ('http://test.com' as ns0)
set #MyText =
(
select
a.bo.value('(/ns0:TestXML2[1]/TestXML3)[1]','INT') as [Number]
from #MyXML.nodes('ns0:TestXML') a(bo)
)
)
Any help would be greatly appreciated, thank you. Also if my logic is completely off about how SQL works with XML, please don't hesitate to educate me.
How's this, it returns 11 from the provided XML which is what you want I assume:
declare #MyText varchar(10)
declare #MyXML XML
set #MyXML = '
<ns0:TestXML xmlns:ns0="http://test.com">
<TestValue>11</TestValue>
</ns0:TestXML>'
;with XMLNAMESPACES ('http://test.com' as ns0)
select #MyText =
a.bo.value('(/ns0:TestXML)[1]','INT')
from #MyXML.nodes('ns0:TestXML') a(bo)
select #MyText as [TheImpossibleValue]