使用SSIS Script任务从变量对象LoadXml读取XML失败

时间:2016-07-28 19:09:39

标签: c# sql-server xml ssis script-task

我有一个构建XML格式数据的SQL语句(SQL server 2014)。我将其拉入SSIS(2013)对象变量。如果我将SQL放入数据流任务以进入文本文件,它就可以工作。但是,没有编码头。由于返回数据的大小,转换为NVARCHAR不是一种选择 - 数据会被切断。

所以,我有一个sql任务,相同的查询: ResultSet = XML;变量datatype = Object(如果我尝试字符串则失败)

所以,在这里经过很长时间后 - 我发现了各种使用XmlWriter和XmlWriterSettings的好东西。太棒了,很棒。但是 - 我似乎无法让脚本任务(C#)正确地读取(或格式化/定义)XML对象。我一直得到一个" DTS脚本任务在用户代码中遇到了异常"

我在LoadXML语句中设置了一个断点 - 验证了变量确实有XML数据 - 有趣的是它被...包围了。在调试模式下,特定错误是"根级别的数据无效。第1行,第1位。"

它在LoadXML语句中抛出异常 - 我错过了什么?我是否需要定义XML布局(字段)?注释掉的测试字符串无问题。没有失败。标题写着。

有什么想法吗?

更新:它也失败了我的测试数据的字符串版本,没有root标记。

public void Main()
        {

            Variables varCollection = null;
            Dts.VariableDispenser.LockForWrite("User::PCC_XML");
            Dts.VariableDispenser.GetVariables(ref varCollection);

            XmlDocument xdoc = new XmlDocument();

            XmlWriterSettings settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                ConformanceLevel = ConformanceLevel.Document,
                OmitXmlDeclaration = false,
                CloseOutput = true,
                Indent = true,
                IndentChars = "  ",
                NewLineHandling = NewLineHandling.Replace
            };    

            xdoc.LoadXml(varCollection["User::PCC_XML"].Value.ToString());

            //xdoc.LoadXml("<xml><foo></foo></xml>");

            using ( StreamWriter sw = File.CreateText("C:\\test_xml.xml") )
            using ( XmlWriter writer = XmlWriter.Create(sw, settings))
            {
                xdoc.WriteContentTo(writer);
                writer.Close();
            }    

            Dts.TaskResult = (int)ScriptResults.Success;
        }

我的XML的瘦身版本(包括已添加的ROOT)

<ROOT>
    <Universal_letters>
        <Universal_letter>
            <docID>123456</docID>
            <Letter_Code>123</Letter_Code>
            <Callback_Phone>1-888-111-111</Callback_Phone>
            <Delivery_Methods>
                <Delivery_Method />
                <Print_Queue />
            </Delivery_Methods>
            <Requested_Date>2016-07-28</Requested_Date>
            <Consumer_First_Name>Bubba</Consumer_First_Name>
            <Consumer_Last_Name>Bubbster</Consumer_Last_Name>
            <Consumer_Address_1>123 Street Way</Consumer_Address_1>
        </Universal_letter>
    </Universal_letters>
</ROOT>

2 个答案:

答案 0 :(得分:0)

您是否尝试删除XML元素之间的间距或检查是否有任何特殊字符。你的XML很好,脚本任务中的C#代码也在做它的工作。 我重新创建了与查询中提到的相同的方案。 所以,我认为问题实际上是在运行时生成的实际XML并设置为PCC_XML变量的输入。它可能被写入变量的方式可能有些可疑。某些间距或特殊字符可能会导致相同的情况发生。 如果有帮助,请将其标记为已回答。

答案 1 :(得分:0)

我无法像Mohd建议的那样让我的XML样本工作。然而,今天,我发现了这个http://www.sql-server-performance.com/2013/export-to-xml-using-ssis/(使用字符串作为结果集,以及转换和导出XML的脚本任务。) https://stackoverflow.com/a/14840090/4509043 - 用于编码。找到了我需要的地方。

有趣的是,c#脚本任务并没有截断我的任何大数据 - 与NVARCHAR(MAX)不同。这太棒了!还值得一提的是OLE DB连接不起作用,它必须是ADO.NET。

最终解决方案: User :: PCC_XML是一种字符串数据类型。 SQL任务具有单行结果 - XML类型。

我的最终工作C#代码是:

在命名空间声明之前 - 使用其他命名空间

using System.Xml; //added - for xml
using System.Text; //added - for Encoding
using System.IO; // added - for file writing

主要过程

public void Main()
        {

            XmlDocument xdoc = new XmlDocument();

            // will ensure that XML exported will have opening tag
            // <?xml version="1.0" encoding="UTF-8"?>
            XmlWriterSettings settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8,
                ConformanceLevel = ConformanceLevel.Document,
                OmitXmlDeclaration = false,
                CloseOutput = true,
                Indent = true,
                IndentChars = "  ",
                NewLineHandling = NewLineHandling.Replace
            };

            // strip out the <root> </root> tags on insert into string
            string strXML = Dts.Variables["User::PCC_XML"].Value.ToString().Replace("<ROOT>", "").Replace("</ROOT>", "");

            xdoc.LoadXml(strXML.ToString());

            // test destination
            using ( StreamWriter sw = File.CreateText("C:\\test_xml.xml") )
            using ( XmlWriter writer = XmlWriter.Create(sw, settings))
            {
                xdoc.WriteContentTo(writer);
                writer.Close();
            }

            Dts.TaskResult = (int)ScriptResults.Success;
        }