如何在OPENXML中使用命名空间属性?

时间:2016-08-11 20:55:38

标签: sql-server xml tsql

我尝试使用T-SQL's OPENXML函数将XML解析为表格形式,但在存在命名空间属性的情况下,我一直会遇到误导性错误。

例如,SQL Server声称有关这个格式良好的XML文档的内容如下:

DECLARE @hdoc int;
DECLARE @doc varchar(1000);

SET @doc =
'
<?xml version="1.0" encoding="UTF-8"?>

<Data xmlns="http://www.digitalmeasures.com/schema/data" xmlns:dmd="http://www.digitalmeasures.com/schema/data-metadata" dmd:date="2016-06-13">
    <Record userId="123456" username="jeffp" termId="129" dmd:surveyId="1234567">
        <dmd:IndexEntry indexKey="AACSBSUFF" entryKey="Participating" text="Participating"/>
        <dmd:IndexEntry indexKey="DEPARTMENT" entryKey="WCBD" text="WCBD"/>
        <dmd:IndexEntry indexKey="QUALIFICATION" entryKey="Instructional Practitioner" text="Instructional Practitioner"/>
        <dmd:IndexEntry indexKey="RANK" entryKey="Academic Staff" text="Academic Staff"/>
        <GENSERVE id="33426841601" dmd:lastModified="2011-03-15T10:23:01" dmd:startDate="2010-07-01">
            <TYPE>University</TYPE>
            <TYPEOTHER/>
            <ORG>University Academic Advising Council   </ORG>
            <ROLE>Committee Member</ROLE>
            <ROLEOTHER/>
            <OFFICE>President/Elect/Past</OFFICE>
            <RESPONSIBILITIES/>
            <NUMHOURS/>
            <ELECAPP>Elected</ELECAPP>
            <AUDIENCE>Local</AUDIENCE>
            <EXOFFICIO/>
            <DTM_START>July</DTM_START>
            <DTD_START/>
            <DTY_START>2010</DTY_START>
            <START_START>2010-07-01</START_START>
            <START_END>2010-07-31</START_END>
            <DTM_END/>
            <DTD_END/>
            <DTY_END/>
            <END_START></END_START>
            <END_END></END_END>
        </GENSERVE>
    </Record>
</Data>
';

EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc;

SELECT    *
FROM       OPENXML (@hdoc, '/Data/Record/GENSERVE', 2)
           with(TYPE varchar(250),
                ORG varchar(250)  )

exec sp_xml_removedocument @hdoc;
The XML parse error 0xc00ce55e occurred on line number 20, near the XML text "            <AUDIEN".
The error description is 'Element was not closed.'.

嗯,这太荒谬了,因为如果我只是删除这些行:

    <dmd:IndexEntry indexKey="AACSBSUFF" entryKey="Participating" text="Participating"/>
    <dmd:IndexEntry indexKey="DEPARTMENT" entryKey="WCBD" text="WCBD"/>
    <dmd:IndexEntry indexKey="QUALIFICATION" entryKey="Instructional Practitioner" text="Instructional Practitioner"/>
    <dmd:IndexEntry indexKey="RANK" entryKey="Academic Staff" text="Academic Staff"/>

然后我没有错误 - 但也没有数据 - 只是空列。

只有当我浏览并删除对任何命名空间的每个引用时,它才会起作用。

<?xml version="1.0" encoding="UTF-8"?>
<Data>
    <Record userId="123456" username="jeffp" termId="129">
        <GENSERVE id="33426841601" >
            <TYPE>University</TYPE>
            <TYPEOTHER/>
            <ORG>University Academic Advising Council   </ORG>
            <ROLE>Committee Member</ROLE>
            <ROLEOTHER/>
            <OFFICE>President/Elect/Past</OFFICE>
            <RESPONSIBILITIES/>
            <NUMHOURS/>
            <ELECAPP>Elected</ELECAPP>
            <AUDIENCE>Local</AUDIENCE>
            <EXOFFICIO/>
            <DTM_START>July</DTM_START>
            <DTD_START/>
            <DTY_START>2010</DTY_START>
            <START_START>2010-07-01</START_START>
            <START_END>2010-07-31</START_END>
            <DTM_END/>
            <DTD_END/>
            <DTY_END/>
            <END_START></END_START>
            <END_END></END_END>
        </GENSERVE>
    </Record>
</Data>
TYPE          ORG
University    University Academic Advising Council

我怎样才能读入命名空间属性?

1 个答案:

答案 0 :(得分:2)

您的XML字符串被截断,因为其长度超过varchar(1000),因此XML解析错误。错误消息与命名空间无关。

现在出现命名空间问题。请注意,您的XML具有默认命名空间(声明的命名空间不带前缀)。查询中涉及的所有元素都隐式地从Data元素继承默认命名空间。您需要将前缀映射到默认命名空间URI,并使用该前缀在OPENXML查询中引用命名空间中的元素:

DECLARE @doc varchar(5000);

.....

EXEC sp_xml_preparedocument @hdoc OUTPUT, 
     @doc, 
    '<Data xmlns:d="http://www.digitalmeasures.com/schema/data" />';

SELECT    *
FROM       OPENXML (@hdoc, '/d:Data/d:Record/d:GENSERVE', 2)
           with(TYPE varchar(250) 'd:TYPE',
                ORG varchar(250) 'd:ORG' )

如果在SQL Server版本中可用,您可能需要考虑使用SQL Server的XQuery和XML数据类型:

DECLARE @xml XML = 'your xml string here'

;WITH XMLNAMESPACES (DEFAULT 'http://www.digitalmeasures.com/schema/data' )
SELECT 
    t.c.value('TYPE[1]', 'VARCHAR(100)' )  AS TYPE,
    t.c.value( 'ORG[1]', 'VARCHAR(100)' ) AS ORG
FROM @xml.nodes('/Data/Record/GENSERVE') t(c)