我使用SP Web服务从GetListItems中提取数据。我希望尽可能多的数据,因为我将其存储到本地XML文档中。我也尝试从数据中创建TSV。 / p>
返回的XML是这样的:
<rs:data ItemCount="896" xmlns:rs="urn:schemas-microsoft-com:rowset">
<z:row ows_A="1" ows_B="2" xmlns:z="#RowsetSchema" />
每行实际上接近60多个属性,问题是每个“行”的返回属性不一致(例如,一些有60个,有些有67个,有些有59个等)。
如果我明确要求按名称提供属性,那不是什么大问题:
foreach (System.Xml.XmlNode listItem in nodeListItems)
{
if (listItem.Name == "rs:data")
{
for (int i = 0; i < listItem.ChildNodes.Count; i++)
{
if (listItem.ChildNodes[i].Name == "z:row")
{
wtSr.Append(listItem.ChildNodes[i].Attributes["ows_Title"].Value);
wtSr.Append("\t");
等等。
我尝试使用类似
之类的东西解析所有属性for (int k = 0; k < listItem.ChildNodes[i].Attributes.Count; k++)
{
tmpWtCol = listItem.ChildNodes[i].Attributes[k].Name.ToString().Replace("ows_", string.Empty).Replace("_", string.Empty);
wtSr.Append(tmpWtCol + "\t");
wtDidHeaders = true;
}
获取可能的属性,但我意识到它只会拾取第一行,这可能有也可能没有最大属性。我想过解析整个事情。虽然不太可能,但我也没有真正的方法知道“最大计数”行是否包含每个组合。
对于“null”(缺失)属性是否有更优雅的解决方案并确定所有属性以创建可接受的“列列表”?
答案 0 :(得分:1)
如果你可以灵活地使用XmlReader,你可以这样做:
HashSet<string> attributeNames = new HashSet<string>();
xmlReader = listItem.CreateNavigator().ReadSubtree();
while (xmlReader.Read())
{
if (xmlReader.NodeType == XmlNodeType.Element
&& xmlReader.Name == "rs:data")
{
if (xmlReader.HasAttributes)
{
int attributeCount = xmlReader.AttributeCount;
for (int i = 0; i < attributeCount; i++)
{
xmlReader.MoveToAttribute(i);
attributeNames.Add(xmlReader.Name);
}
}
}
}
答案 1 :(得分:0)
您最好的选择是了解从中获取项目的列表的架构。这样,您还可以找到字段的内部名称(xml格式:ows_部分)。
答案 2 :(得分:0)
创建一个Serializable
类来保存所有文档。 (正如 JamesLove 所说,您需要知道您尝试解析的架构XML文档。)
您可以使用[XmlElement]
等属性标记类的数据保持属性(请参阅MSDN上的更多内容),以控制类的对象(de)序列化的方式。目标(在许多情况下可实现)是标记它,以便只需一次调用XmlSerializer
即可完成(反)序列化。
作为一般规则,请尽量减少代码中自定义,过程式XML解析例程的数量。 XML序列化不是一个特性,它是最终用户和客户完全不关心的东西。
答案 3 :(得分:0)
我认为你的问题的核心是你想要知道#RowsetSchema
命名空间中row
命名空间中那些元素上出现的所有属性(不包括命名空间声明)的唯一名称。 1}}。
LINQ是你的朋友:
foreach (string s in doc.Descendants()
.Where(x => x.Name.NamespaceName == "#RowsetSchema")
.Attributes()
.Where(x => !x.IsNamespaceDeclaration)
.Select(x => x.Name.LocalName)
.Distinct())
{
Console.WriteLine(s);
}