使用命名空间修改xml

时间:2012-10-19 11:52:22

标签: sql sql-server xml tsql xsd

我正在尝试在TSQL中修改预定义的xml(xsd更具体)。 我想在其中一个xsd元素中插入枚举限制。

任务是根据查询填写xsd限制 例如:

create table #list(value nvarchar(100))
insert into #list values('item 1')
insert into #list values('item 2')
insert into #list values('item 3')
insert into #list values('item 4')
insert into #list values('item 5')
insert into #list values('item 6')

declare @enumeration as xml
;with xmlnamespaces('http://www.w3.org/2001/XMLSchema' as xs)
select @enumeration = (
    select value as '@value'
    from #list for xml path('xs:enumeration')
)

declare @schema xml
set @schema =
'<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="test">
    <xs:element name="test" msdata:IsDataSet="true" msdata:MainDataTable="Example" msdata:UseCurrentLocale="true">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element name="Example">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="myList" minOccurs="1" nillable="false">
                                <xs:simpleType>
                                    <xs:restriction base="xs:string">
                                        <xs:maxLength value="50" />
                                    </xs:restriction>
                                </xs:simpleType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:choice>
        </xs:complexType>
    </xs:element>
</xs:schema>'

set @schema.modify
    ('insert sql:variable("@enumeration")
    into (//xs:element[@name=''myList'']/xs:simpleType/xs:restriction)[1]')

select @schema

问题是代码输出了不必要的xmlns属性

<xs:enumeration xmlns:xs="http://www.w3.org/2001/XMLSchema" value="item 1" />

有人可以帮忙吗?

3 个答案:

答案 0 :(得分:1)

它比我希望的更难看。主要是因为我无法在sql:variable("@enumeration")/delete-me/node()内使用.modify()

我假设您可以修改@enumeration的生成,如下所示:

CREATE TABLE #list (value nvarchar(100));
INSERT  INTO #list
VALUES  ('item 1');
INSERT  INTO #list
VALUES  ('item 2');
INSERT  INTO #list
VALUES  ('item 3');
INSERT  INTO #list
VALUES  ('item 4');
INSERT  INTO #list
VALUES  ('item 5');
INSERT  INTO #list
VALUES  ('item 6');

DECLARE @enumeration AS xml;
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema' AS xs)
SELECT @enumeration = (
    SELECT value AS '@value'
    FROM #list FOR XML PATH('xs:enumeration'), ROOT('delete-me'), TYPE
);

我们的想法是将FOR XMLROOT一起使用,以便生成的命名空间位于不必要的根元素(可以跳过)。否则,我们必须稍后重新创建xs:enumeration - 元素。

两种解决方案

使用.modify()三次

这个想法:

  1. 我们将@enumeration(带有不必要的根)的所有内容插入到其他xml
  2. 我们将所需内容复制到正确的位置
  3. 我们删除@enumeration中不再需要的@schema副本。
  4. DECLARE @schema xml;
    SET @schema = '<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="test">
        <xs:element name="test" msdata:IsDataSet="true" msdata:MainDataTable="Example" msdata:UseCurrentLocale="true">
            <xs:complexType>
                <xs:choice maxOccurs="unbounded">
                    <xs:element name="Example">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="myList" minOccurs="1" nillable="false">
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:maxLength value="50" />
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:element>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                </xs:choice>
            </xs:complexType>
        </xs:element>
    </xs:schema>';
    
    SET @schema.modify('insert sql:variable("@enumeration")
        into /');
    
    SET @schema.modify('declare namespace xs="http://www.w3.org/2001/XMLSchema";
    insert /delete-me/node()
        into (//xs:element[@name=''myList'']/xs:simpleType/xs:restriction)[1]');
    
    SET @schema.modify('delete /delete-me');
    
    SELECT  @schema;
    
    DROP TABLE #list;
    

    .query()创建@schema

    如果您可以更改创建@schema的部分,则可以@schema直接生成.query() @enumeration

    DECLARE @enumeration AS xml;
    WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema' AS xs)
    SELECT @enumeration = (
        SELECT value AS '@value'
        FROM #list FOR XML PATH('xs:enumeration'), ROOT('delete-me'), TYPE
    );
    
    DECLARE @schema xml;
    SET @schema = @enumeration.query('<xs:schema xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="test">
        <xs:element name="test" msdata:IsDataSet="true" msdata:MainDataTable="Example" msdata:UseCurrentLocale="true">
            <xs:complexType>
                <xs:choice maxOccurs="unbounded">
                    <xs:element name="Example">
                        <xs:complexType>
                            <xs:sequence>
                                <xs:element name="myList" minOccurs="1" nillable="false">
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:maxLength value="50" />
                                            {/delete-me/node()}
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:element>
                            </xs:sequence>
                        </xs:complexType>
                    </xs:element>
                </xs:choice>
            </xs:complexType>
        </xs:element>
    </xs:schema>');
    
    SELECT  @schema;
    

答案 1 :(得分:0)

如果xml不是太大,你可以做一个简单的字符串替换:

DECLARE @schemaVARCHAR (MAX)
SET @schemaVARCHAR = CAST(@schema AS VARCHAR(MAX))
SET @schemaVARCHAR = 
    REPLACE(
        @schemaVARCHAR, 
        '<xs:enumeration xmlns:xs="http://www.w3.org/2001/XMLSchema" value="item 1" />',
        ''
    )

SET @schema = CAST(@schemaVARCHAR AS XML)

答案 2 :(得分:0)

如果您的XML不太复杂,为什么不使用FOR XML EXPLICIT呢?

另一种解决方法是在没有命名空间的情况下生成XML,然后再添加它。