我正在使用XMLSerialization工具解析XML文档。示例XML文件由paragraphs
(string
)和tables
组成,它们是复杂的XML类型。 Tables
由一系列row
组成,其中包含一系列entry
(string
)
我需要跟踪每个table
相对于每个paragraph
的位置。有没有办法在XMLSerialization工具解析时捕获每个table
的位置?或者我是否需要使用[XMLAnyElement]
等结构并按顺序解析每个paragraph
和table
以跟踪table
位置?我宁愿避免这种方法,因为我的真实XML文件有许多级别需要手动解析。我有一种感觉,我错过了一些非常明显的东西,但我一直在搜索并尝试多种方法,但没有直接的解决方案。
这是我的基本代码:
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace XMLDeserializeTest
{
class Program
{
static void Main(string[] args)
{
string file = Environment.CurrentDirectory + @"\test.xml";
test testClass = Deserialize(file);
}
static test Deserialize(string url)
{
XmlSerializer reader =
new XmlSerializer(typeof(test));
StreamReader stream = new StreamReader(url);
return reader.Deserialize(stream) as test;
}
}
public class test
{
[XmlElement("paragraph")]
public List<string> paragraphs { get; set; }
[XmlElement("table")]
public List<Table> tables { get; set; }
public test()
{
}
}
public class Table
{
[XmlElement("row")]
public List<Row> rows { get; set; }
public int nodeNumber { get; set; } // This is what needs to be tracked
public Table()
{
}
}
public class Row
{
[XmlElement("entry")]
public List<string> entries { get; set; }
public Row()
{
}
}
我的示例XML:
<?xml version="1.0" encoding="utf-8" ?>
<test>
<paragraph>Here is some text.</paragraph>
<paragraph>Here is some more text. The table follows this paragraph.</paragraph>
<table>
<row>
<entry>1</entry>
<entry>2</entry>
<entry>3</entry>
</row>
<row>
<entry>4</entry>
<entry>5</entry>
<entry>6</entry>
</row>
</table>
<paragraph>This is the last paragraph. This comes after the table.</paragraph>
</test>
我想出了一个使用XDocument的解决方案,但它看起来很笨拙:
XDocument Xdoc = XDocument.Load(file);
int numParagraphs = 0;
int tableNumber = 0;
foreach(XElement item in Xdoc.Root.Descendants())
{
if (item.Name.LocalName.Equals("paragraph"))
{
numParagraphs++;
}
else if (item.Name.LocalName.Equals("table"))
{
testClass.tables[tableNumber].nodeNumber = numParagraphs;
tableNumber++;
}
}
答案 0 :(得分:1)
一个选项只是在序列化时将表的段落“index”序列化为XML。这样你就不必做任何自定义的事情了。
但是,要使用XmlSerializer执行您要查找的内容,您可以使用UnknownElement事件自行处理某些元素类型的反序列化。请注意,已从测试类中删除了XmlElement属性,以便处理表和段落元素。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace XMLDeserializeTest
{
class Program
{
static int paragraphCount = 0;
static void Main(string[] args)
{
string file = Environment.CurrentDirectory + @"\test.xml";
paragraphCount = 0;
test testClass = Deserialize(file);
}
static test Deserialize(string url)
{
XmlSerializer serializer = new XmlSerializer(typeof(test));
serializer.UnknownElement += serializer_UnknownElement;
StreamReader stream = new StreamReader(url);
return serializer.Deserialize(stream) as test;
}
static void serializer_UnknownElement(object sender, XmlElementEventArgs e)
{
test t = (test)e.ObjectBeingDeserialized;
if (e.Element.Name == "table")
{
var s = new XmlSerializer(typeof(Table));
var sr = new StringReader(e.Element.OuterXml);
Table newTable = s.Deserialize(sr) as Table;
newTable.nodeNumber = paragraphCount;
t.tables.Add(newTable);
}
else if (e.Element.Name == "paragraph")
{
String paragraphText = e.Element.InnerText;
t.paragraphs.Add(paragraphText);
paragraphCount++;
}
}
}
public class test
{
public List<string> paragraphs { get; set; }
public List<Table> tables { get; set; }
public test()
{
}
}
[Serializable, XmlRoot("table")]
public class Table
{
[XmlElement("row")]
public List<Row> rows { get; set; }
public int nodeNumber { get; set; } // This is what needs to be tracked
public Table()
{
}
}
[Serializable, XmlRoot("row")]
public class Row
{
[XmlElement("entry")]
public List<string> entries { get; set; }
public Row()
{
}
}
}