我有一个大的(~40mb)XML数据集合,分成许多文件格式不正确,所以我合并它们,添加一个根节点并在XmlDocument
中加载所有xml。它基本上是3种不同类型的列表,可以通过几种不同的方式嵌套。此示例应显示大多数情况:
<Root>
<A>
<A>
<A></A>
<A></A>
</A>
</A>
<A />
<B>
<A>
<A>
<A></A>
<A></A>
</A>
</A>
</B>
<C />
</Root>
通过在XmlDocument
(//A
,//B
,//C
)上使用XPath表达式来分隔所有A,B和C节点,将生成的节点集转换为数据表并在Datagridview中分别显示每个节点类型的所有节点的列表。这很好。
但是现在我面对的是一个更大的文件,只要我加载它,它就会显示我只有4行。然后我在实际XmlDocument.SelectNodes
发生的行添加了一个断点,并检查了结果NodeSet
。它向我展示了大约25,000个条目。继续加载程序并呐喊后,我的所有25k行都显示出来。我再试一次,我可以重现它。如果我手动跨步XmlDocument.SelectNodes,它的工作原理。如果我不打破那里,它不会。我不会在我的应用程序中生成单个线程。
我如何进一步调试?要找什么?我遇到过像jsch(ssh)这样的多线程库的这种行为,但我不知道为什么在我的情况下会发生这种情况。
非常感谢!
// class XmlToDataTable:
private DataTable CreateTable(NamedXPath logType,
List<XmlColumn> columns,
ITableCreator tableCreator)
{
// I have to break here -->
XmlNodeList xmlNodeList = logFile.GetEntries(logType);
// <-- I have to break here
DataTable dataTable = tableCreator.CreateTableLayout(columns);
foreach (XmlNode xmlNode in xmlNodeList)
{
DataRow row = dataTable.NewRow();
tableCreator.PopulateRow(xmlNode, row, columns);
dataTable.Rows.Add(row);
}
return dataTable;
}
// class Logfile:
public XmlNodeList GetEntries(NamedXPath e)
{
return (_xmlDocument != null && _xmlDocument.HasChildNodes)
? _xmlDocument.SelectNodes(e.XPath)
: new XmlNullObjectNodeList();
}
// _xmlDocument gets loaded here after reading all xml fragments into a string
// (ugly, i know. the // ugly! comment reminds me about that ;))
private void CreateXmlDoc()
{
_xmlDocument = new XmlDocument();
_xmlDocument.LoadXml(OPEN_ROOT_ELEMENT + _xmlString +
CLOSE_ROOT_ELEMENT);
if (DataChanged != null)
DataChanged(this, new EventArgs());
}
// class NamedXPath:
public abstract class NamedXPath
{
private readonly String _name;
private readonly String _xPath;
protected NamedXPath(string name, string xPath)
{
_name = name;
_xPath = xPath;
}
public string Name
{
get { return _name; }
}
public string XPath
{
get { return _xPath; }
}
}
答案 0 :(得分:1)
不是先在代码中直接使用XPath,而是使用sketchPath这样的工具来使我的XPath正确。您可以加载原始XML或使用原始XML的子集。
使用XPath和XML来查看在代码中使用xpath之前是否选择了预期的节点。
答案 1 :(得分:0)
好的,解决了。 tableCreator
是我的策略模式的一部分,它会影响表的构建方式。在某个实现中,我做了类似这样的事情:
XmlNode xn = xmlDocument.SelectSingleNode(fancyXPath);
// if a node has ancestors, then its a linked list:
// <a><a><a></a></a></a>
if(xn.SelectSingleNode("a") != null)
xn.SelectSingleNode("a").InnerText = "<IDs of linked list items CSV like here>";
这意味着我用一些文本替换xml链表的一部分并丢失那里的嵌套项。
如果此更改不会影响原始XmlDocument
,则找到此错误不会有问题。即便如此,调试它也不应该太难。是什么让我的程序表现不同取决于我是否休息似乎如下:
返回值: 第一个XmlNode 匹配XPath查询,如果不匹配,则返回null 找到匹配节点。 XmlNode 不应该被期望连接 “直播”到XML文档。那是, XML中出现的更改 文件可能不会出现在 XmlNode,反之亦然。 (API XmlNode.SelectNodes())
的描述
如果我在那里中断,更改将被写回原始的XmlDocument,如果我没有中断,则不会写回。无法真正向我自己解释,但如果没有XmlNode的变化,一切正常。
编辑:
现在我非常肯定:我的手表中有XmlNodeList.Count。这意味着,每次我调试时,VS都会调用属性Count
,它不仅会返回一个数字,而是调用ReadUntil(int),刷新内部列表:
internal int ReadUntil(int index)
{
int count = this.list.Count;
while (!this.done && (count <= index))
{
if (this.nodeIterator.MoveNext())
{
XmlNode item = this.GetNode(this.nodeIterator.Current);
if (item != null)
{
this.list.Add(item);
count++;
}
}
else
{
this.done = true;
return count;
}
}
return count;
}
这可能导致了这种奇怪的行为。