使用XPath根据输入文件中的选项卡计数创建XML节点 [英] Creating XML nodes based on a tab count from input file using XPath

查看:90
本文介绍了使用XPath根据输入文件中的选项卡计数创建XML节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用C#创建XML文档作为输出,其父节点基于输入文件中选项卡的数量.我正在尝试使用XPath确定父节点.我已经阅读了源文件并将其保存为列表,并且能够将部分数据保存为所需的属性,但是子节点的顺序不符合预期.它将它们置于预期的级别",但不在正确的父项之下.我的XPath似乎没有获得我期望的父级,但是我不确定XPath出了什么问题.它似乎可以工作到Filename8(在示例中),但是它将Filename9放在Filename 7下,然后在树的下方找到Filename8.当然,这只是输入文件的一小部分,但我希望您能理解我正在尝试做的事情.任何建议将不胜感激!
这是我的代码的一部分:

I am trying to create an XML document as output using C# with the parent node being based on the count of tabs from the input file. I am trying to use XPath to determine the parent node. I have read the source file in and saved it as a list, and I am able to get the parts of the data saved as the attributes that I need, but the child nodes are not in the expected order. It is putting them in the expected "level", but not under the correct parent. My XPath seems to not be getting the parent that I expect it to, but I am not sure what is wrong with the XPath. It seems to work down to Filename8 (in the example), but it would put Filename9 under Filename 7 and then Filename8 would be found lower down in the tree. Of course this is a small sample of the input file, but I hope you will understand what I am trying to do. Any suggestions would be greatly appreciated!
Here is part of my code:

//Loop through the list to create the child nodes
            for (int i = 0; i < lines.Count; i++)
            {
              // if the line starts with /* then it is a comment, 
              // skip and go to next line
                if (lines[i].StartsWith("/*"))
                {
                    continue;
                }
                tabCount = 0;
                tabCount = lines[i].Count(c => c == '\t');  

                //get the title of the line
                if (lines[i].Contains("/*"))
                {
                    titleIndex = lines[i].IndexOf("/*");
                    endTitleIndex = lines[i].IndexOf("*/");
                    title = lines[i].Substring(titleIndex + 2, endTitleIndex - titleIndex - 2).Trim();
                }
                else
                {
                    titleIndex = lines[i].Length;
                }

                //get the file name
                filename = lines[i].Substring(0, titleIndex).Trim();

                //create the element and add the filename attribute
                XmlElement tocEntry = doc.CreateElement("tocEntry");   
                tocEntry.SetAttribute("filename", filename);
                
                //if the title not blank add title attribute
                if (title.Length > 0)
                {
                    tocEntry.SetAttribute("title", title);
                }

                //Add in a tabCount attribute to help determine the parent node.
                tocEntry.SetAttribute("tabCount", tabCount.ToString());

                //If the tabCount is 0 then add the node to the root
                if (tabCount == 0)
                {
                    root.AppendChild(tocEntry);
                }
                //If the tabCount is not 0 then add as a child to the parent.
                else 
                {
                    XmlNode parent = root.SelectSingleNode("//tocEntry[@tabCount='" + (tabCount - 1) + "'][last()]");
                    parent.AppendChild(tocEntry);
                }               
               
            }


这是输入文件的一个小样本:
.. \ filename1.xml/*标题1 */
/t..\filename2.xml/*标题2 */
/t/t..\filename3.xml/*标题3 */
/t/t..\filename4.xml/*标题4 */
/t/t..\filename5.xml/*标题5 */
/t/t..\filename6.xml/*标题6 */
/t/t..\filename7.xml/* TITLE 7 */
/t..\filename8.xml/*标题8 */
/t/t..\filename9.xml/*标题9 */
/t/t/t..\filename10.xml/*标题10 */
/t/t/t/t..\filename11.xml/* TITLE 11 */

所需的输出样本:


Here is a small sample of the input file:
..\filename1.xml /* TITLE 1 */
/t..\filename2.xml /* TITLE 2 */
/t/t..\filename3.xml /* TITLE 3 */
/t/t..\filename4.xml /* TITLE 4 */
/t/t..\filename5.xml /* TITLE 5 */
/t/t..\filename6.xml /* TITLE 6 */
/t/t..\filename7.xml /* TITLE 7 */
/t..\filename8.xml /* TITLE 8 */
/t/t..\filename9.xml /* TITLE 9 */
/t/t/t..\filename10.xml /* TITLE 10 */
/t/t/t/t..\filename11.xml /* TITLE 11 */

Desired output sample:

<Entry filename="..\filename1.xml" title="TITLE 1">
     <Entry filename="..\filename2.xml" title="TITLE 2">
        <Entry filename="..\filename3.xml" title="TITLE 3"/>
        <Entry filename="..\filename4.xml" title="TITLE 4"/>
        <Entry filename="..\filename5.xml" title="TITLE 5"/>
        <Entry filename="..\filename6.xml" title="TITLE 6"/>
        <Entry filename="..\filename7.xml" title="TITLE 7"/>
     </Entry>
     <Entry filename="..\filename8.xml" title="TITLE 8">
        <Entry filename="..\filename9.xml" title="TITLE 9">
           <Entry filename="..\filename10.xml" title="TITLE 10">
               <Entry filename="..\filename11.xml" title="TITLE 11"/>
           </Entry>
        </Entry>
     </Entry>
 </Entry>

推荐答案

看不到xpath的错误,但是当解析文件名为filename10.xml的行时,查询返回到节点(文件名7. xml和filename9.xml). SelectSingleNode选择第一个节点(filename7.xml).

因此,当您更改
Don''t see the error in you''re xpath, but when parsing the line with filename10.xml the query returns to nodes (filename7.xml and filename9.xml). SelectSingleNode selects the first node (filename7.xml).

So when you change
XmlNode parent = root.SelectSingleNode("//tocEntry[@tabCount=''" + (tabCount - 1) + "''][last()]");
parent.AppendChild(tocEntry);



放入




it into


XmlNodeList parent = root.SelectNodes("//tocEntry[@tabCount=''" + (tabCount - 1) + "''][last()]");
parent[parent.Count -1].AppendChild(tocEntry);



您会得到预期的结果

问候

Piet



you get the expected result

Regards

Piet


这篇关于使用XPath根据输入文件中的选项卡计数创建XML节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆