将xml的sharepoint列表转换为数据集

时间:2016-03-04 10:37:00

标签: c# xml vb.net sharepoint soap

已经超过一周,我仍然无法弄清楚这里有什么问题。希望你能帮助我。我正在使用SOAP Web服务从共享点服务器成功检索xml,然后我将xml转换为数据集对象,我正在成功获取数据集但其“已损坏” - 很少有列具有xml中缺少的值。 这里是使用SOAP导入xml的代码:

        private void button2_Click(object sender, EventArgs e)
        {
            oportal.Lists list = new oportal.Lists();
            list.Credentials = System.Net.CredentialCache.DefaultCredentials;
            list.Url = "http://xxx/xxx/xxx/xxx/_vti_bin/Lists.asmx";

            XmlDocument xmlDoc = new System.Xml.XmlDocument();

            XmlNode ndQUery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
          XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
            XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");

            ndQueryOptions.InnerXml =
             "<IncludeMandatoryColumns>TRUE</IncludeMandatoryColumns>" +
             "<DateInUtc>FALSE</DateInUtc>";

            ndViewFields.InnerXml = @"<FieldRef Name='שם לקוח' />
    <FieldRef Name='שם מתל'/>";




            try
            {
                XmlNode ndListItems = list.GetListItems("{DD1CF626-62E1-4E36-BF2B-C7D08EA73674}",null, ndQUery, ndViewFields, "14000", ndQueryOptions, null);
               System.Diagnostics.Debug.WriteLine(ndListItems.OuterXml);

               dataGridView1.DataSource = ConverttYourXmlNodeToDataSet(ndListItems).Tables[1];
            }
            catch(System.Web.Services.Protocols.SoapException ex) {
                MessageBox.Show(ex.Message + Environment.NewLine + ex.Detail.InnerText + Environment.NewLine + ex.StackTrace);

            }

        }

xml我看起来没问题,列(字段)名称是希伯来语,但xml在HTML实体(十六进制)中显示它们 - 也许这就是问题的根源?

我得到xml后我将它转换为带有ConverttYourXmlNodeToDataSet()函数的数据集,这里是代码:

 public static DataSet ConverttYourXmlNodeToDataSet(XmlNode xmlnodeinput)
        {
            DataSet dataset = null;
            if (xmlnodeinput != null)
            {
                XmlTextReader xtr = new XmlTextReader(xmlnodeinput.OuterXml, XmlNodeType.Element,null);
                dataset = new DataSet();
                dataset.ReadXml(xtr);
            }

            return dataset;
        } 

我正在成功获得数据集,但就像我提到它因缺失值而受损,它们存在于xml中而不存在于数据集中(列存在但不存在值)。

请看一下这个屏幕拍摄:

Dataset of sharepoint list xml

iv`e用红色包围,其中一列没有从XML中获取它们的值。 这里是xml的屏幕截图以及应该在红色数据集中的缺失值:

XML of sharepoint list

还尝试将xml转换为这样的数据集,但结果是相同的:

public static DataSet read(XmlNode x) { 

        DataSet ds = new DataSet();

        XmlReader r = new XmlNodeReader(x);

            ds.ReadXml(r);
            return ds;

        }
希望有人可以帮助我。 TNX。

更新

好吧我还没有解决它,但我发现可能导致解决方案的一些事情:

  1. 我注意到在数据集中没有值的所有列都是用户在网站控件中填充的列,猜猜是什么?这些列的所有标题都是希伯来语,因此在数据集上显示值的列是sharepint默认列,其标题是英文,并且它们没有HTML实体(十六进制)! name(查看xml)。因此,我怀疑该问题与与希伯来语字幕相关的HTML实体(十六进制)列名相关......我的假设是数据集无法解释此HTML实体(十六进制)编码。另一个线索是,列名在数据集中的拼写(例如,查看上面的datagridview的屏幕截图 - 从左侧的第4列(索引3))未被解释为右,列名称应为'שםמתל '那就是全部 - 正如你所看到的那样(你不必理解希伯来语)只有一半的希伯来字符串存在并连接到编码的HTML实体(十六进制)的一部分。

  2. 我注意到,当我使用列的十六进制html实体而不是列的希伯来名称对共享点网站中的列进行排序时所需的URL:

  3. http://xxx/xxx/xxx/xxx/Lists/1/view9.aspx?View= {c2538b95-efae-453B-b536-aad6f98265ed}&安培; =的SortField&_x05e9__x05dd__x0020__x05de__x05放大器; SortDir =说明

    我希望看到类似的内容:

    http://xxx/xxx/xxx/xxx/Lists/1/view9.aspx?View= {c2538b95-efae-453b-b536-aad6f98265ed}&amp; SortField = _'שםמתל'= Desc

    所以我对我的代码进行了更改,以便在编码的HTML实体(十六进制)中显式声明列名,我这样做了(原始代码在上面):

    ndViewFields.InnerXml = @"<FieldRef Name='_x05d0__x05d9__x05e9__x05d5__x05' />
        <FieldRef Name='_x05e9__x05dd__x0020__x05de__x05'/>";
    

    现在我在数据集中获得的结果已经改变了!更改是我明确声明的列移动到数据集的第一列索引但仍然没有这些列中的任何值。

    所以,为了总结所有这些挖掘,这是我的假设:

    *。问题是xml和数据集之间的解释器

    *。解释器有缺陷,因为他无法正确解释经过编码的HTML实体(十六进制)

    *。用HTML实体(十六进制)编写的列标题,因为它们的标题是希伯来语

    *。解决方案可以是或者将列标题设置为普通希伯来语(在xml中)或者做一些能使xml和数据集之间的解释器正常工作的东西(也许使用XmlParserContext类 - 尝试一点没有成功或其他类可以操作编码的xml文本)。

2 个答案:

答案 0 :(得分:0)

最后,在我完成解决这个问题之后。我发现的解决方案非常简单。

我一直在寻找并努力寻找解决方案,从未找到过,然后这个简单的解决方案在我脑海中浮现。

只需要一行代码:

  String s = xmlnodeinput.OuterXml.Replace("ows__x05e9__x05dd__x0020__x05de__x05",
 "AccountManager");

只需替换十六进制值,就可以正确加载数据集。

我还检查过没有时间处理问题(替换字符串需要的时间少于一秒):

开始阅读12000行:26/03/2016 17:18:00 开始更换字符串:26/03/2016 17:18:04 将xml字符串加载到数据集:26/03/2016 17:18:04 完成加载数据集:26/03/2016 17:18:04

从xml到数据集函数的complte转换:

 public static DataSet ConverttYourXmlNodeToDataSet(XmlNode xmlnodeinput)
    {
        //declaring data set object
        DataSet dataset = null;
        if (xmlnodeinput != null)
        {
            NameTable nt = new NameTable();
            nt.Add("row");
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
            XmlParserContext context = new XmlParserContext(nt, null, "heb",null, null, null, null, null, XmlSpace.None,Encoding.Unicode);

            String s = xmlnodeinput.OuterXml.Replace("ows__x05e9__x05dd__x0020__x05de__x05", "AccountManager");

            XmlTextReader xtr = new XmlTextReader(s, XmlNodeType.Element,context);

            dataset = new DataSet();

            dataset.ReadXml(xtr);
        }

        return dataset;
    }

答案 1 :(得分:0)

遇到同样的问题(Xml通过/加载到DataSet后缺少值)。 似乎某些字符存在问题(在我的情况下为“ - ”)。

jonathana解决方案的工作原理(在将数据加载到数据集之前从属性名称替换字符)。

我还将为.NET2提供一个解决方案,它可以更改生成的SharePoint SOAP查询XML中的所有属性名称,以确保对数据集的对话不会导致错误(可以使用.NET3 +更好地完成,但我强迫在我的情况下到.NET2):

using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

XmlDocument doc = new XmlDocument();

doc.LoadXml(spResXml.OuterXml);
System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(doc.NameTable);
nm.AddNamespace("rs", "urn:schemas-microsoft-com:rowset");
nm.AddNamespace("z", "#RowsetSchema");
nm.AddNamespace("rootNS", "http://schemas.microsoft.com/sharepoint/soap");

var zRows = doc.SelectNodes("//z:row", nm);
for (int i = 0; i < zRows.Count; i++)
{
    XmlNode zRow = zRows[i];
    List<XmlAttribute> attsList = new List<XmlAttribute>();
    for (int j = 0; j < zRow.Attributes.Count; j++)
    { attsList.Add(zRow.Attributes[j]); }

    foreach (XmlAttribute att in attsList)
    {
       string patchedAttName = att.Name;
       patchedAttName = patchedAttName.Replace("_x", "%u");
       patchedAttName = HttpUtility.UrlDecode(patchedAttName);
       patchedAttName = Regex.Replace(patchedAttName,"[^A-Za-z0-9_]", "_", RegexOptions.None);
       if (att.Name.Equals(patchedAttName))
       { continue; }
       var newAtt = doc.CreateAttribute(att.Prefix, patchedAttName, att.NamespaceURI);
       newAtt.Value = att.Value;
       zRow.Attributes.Remove(att);
       zRow.Attributes.Append(newAtt);
    }
 }
 DataSet ds = new DataSet();
 ds.ReadXml(new XmlNodeReader(doc));
 DataTable t = ds.Tables[1];