C# 从某个元素向前读取XML节点?
我知道有很多方法可以做到这一点,但我正在寻找一种最简单的方法,而不必使用streamreader或其他更为手动的工具,这将迫使我遍历整个文件并比较无尽的字符串。一种可能是使用streamreader查找特定文本,然后使用一些XML库检索节点 这是我的XML。这就是我需要做的: 1使用要查找的文本查找标记npid的第一个实例 2提取节点提取并存储在某个数据对象中。有几个节点称为NodeToExtract,但我只希望在初始搜索文本后找到第一个节点C# 从某个元素向前读取XML节点?,c#,.net,visual-studio-2010,linq,linq-to-xml,C#,.net,Visual Studio 2010,Linq,Linq To Xml,我知道有很多方法可以做到这一点,但我正在寻找一种最简单的方法,而不必使用streamreader或其他更为手动的工具,这将迫使我遍历整个文件并比较无尽的字符串。一种可能是使用streamreader查找特定文本,然后使用一些XML库检索节点 这是我的XML。这就是我需要做的: 1使用要查找的文本查找标记npid的第一个实例 2提取节点提取并存储在某个数据对象中。有几个节点称为NodeToExtract,但我只希望在初始搜索文本后找到第一个节点 感谢您的帮助。真正的问题是,没有暴力是无法做到这一点
感谢您的帮助。真正的问题是,没有暴力是无法做到这一点的。可以提取相关节点,然后将其加载到xmldocument中 例如:
class Program
{
static void Main(string[] args)
{
string buffer = " blah blah blah " +
"<nw>" +
"<npid>Text to Find</npid>" +
"<r>0</r>" +
"</nw>" +
"</mi>" +
"</ne>" +
"<ne>" +
"<ofid>" +
"<ofun>ABC</ofun>" +
"<ofdn>Blah</ofdn>" +
"<ofsw>18R</ofsw>" +
"</ofid>" +
"<mi>" +
"<mts>Good stuff</mts>" +
"<gp>000</gp>" +
"<mu>Value1</mu>" +
"<mu>Value2</mu>" +
"<mu>Value3</mu>" +
"<mu>Value4</mu>" +
"<mu>Value5</mu>" +
"<nw>" +
"<npid>ABC1221</npid>" +
"<r>99</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"</nw>" +
"<nw>" +
"<npid>ABC1222</npid>" +
"<r>99</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"</nw>" +
"<nw>" +
"<npid>ABC1223</npid>" +
"<r>99</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"</nw>" +
"</mi> blah blah blah";
int indexOf_Text = buffer.IndexOf( "Text to Find" );
XmlDocument nextMiNode = ExtractNode( indexOf_Text, buffer );
// now traverse the node as you please
foreach ( XmlNode node in nextMiNode.ChildNodes[1].ChildNodes )
{
if ( node.Name == "mts" )
{
// Good stuff ?
if ( node.InnerText == "Good stuff" )
Console.WriteLine( node.InnerText );
}
}
Console.ReadKey();
}
static XmlDocument ExtractNode(int indexOf_Text, string buffer)
{
XmlDocument xDoc = new XmlDocument();
StringBuilder sbNode = new StringBuilder();
sbNode.Append( "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
bool inNode = false;
for ( int i = indexOf_Text; i < buffer.Length - 1; i++ )
{
// find the first "<mi>" tag ..
if ( !inNode &&
( buffer[i] == '<' &&
i + 3 < buffer.Length - 1 &&
buffer[i + 1] == 'm' &&
buffer[i + 2] == 'i' &&
buffer[i + 3] == '>' ) )
inNode = true;
if ( inNode ) // capture it
sbNode.Append( buffer[i] );
// find the next "<mi/>" ending tag (only if we found the begining tag : inNode=true)
if ( inNode &&
( buffer[i] == '>' &&
i - 4 >= indexOf_Text &&
buffer[i - 1] == 'i' &&
buffer[i - 2] == 'm' &&
buffer[i - 3] == '/' &&
buffer[i - 4] == '<' ) )
{
break; // we are done
}
}
xDoc.LoadXml( sbNode.ToString() );
return xDoc;
}
}
假设您的意思是mi元素,请尝试这样说,NodeToExtract: 使现代化
您的XML格式不正确,没有可查找的属性文本。ReadSubTree方法就是您想要的方法,我想……我刚知道有人会用您的XML格式不正确进行回复。为了消除混淆,XML文件是400K;我不能发布整个文件,现在可以吗?正如我在帖子中提到的,在14500行中,这一部分是我最感兴趣的。最后,我写错了:有一个名为npid的标记,要查找文本。您现在看到了吗?为了分析XML的结构,您至少需要工作良好的XML片段。请发布一个格式良好的最小示例。我添加了一个格式良好的XML块。效果非常好。最后一件事,您知道如何将query2.First移动到数据集或数据表中吗?谢谢。我最终使用它将结果字符串复制到一个数据集:StringReader stream=null;XmlTextReader=null;数据集xmlDS=新数据集;stream=新的StringReaderxml;reader=新的XmlTextReaderstream;xmlDS.ReadXmlreader;谢谢问题是我会手动解析它,这正是我想要避免的。
class Program
{
static void Main(string[] args)
{
string buffer = " blah blah blah " +
"<nw>" +
"<npid>Text to Find</npid>" +
"<r>0</r>" +
"</nw>" +
"</mi>" +
"</ne>" +
"<ne>" +
"<ofid>" +
"<ofun>ABC</ofun>" +
"<ofdn>Blah</ofdn>" +
"<ofsw>18R</ofsw>" +
"</ofid>" +
"<mi>" +
"<mts>Good stuff</mts>" +
"<gp>000</gp>" +
"<mu>Value1</mu>" +
"<mu>Value2</mu>" +
"<mu>Value3</mu>" +
"<mu>Value4</mu>" +
"<mu>Value5</mu>" +
"<nw>" +
"<npid>ABC1221</npid>" +
"<r>99</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"</nw>" +
"<nw>" +
"<npid>ABC1222</npid>" +
"<r>99</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"</nw>" +
"<nw>" +
"<npid>ABC1223</npid>" +
"<r>99</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"<r>0</r>" +
"</nw>" +
"</mi> blah blah blah";
int indexOf_Text = buffer.IndexOf( "Text to Find" );
XmlDocument nextMiNode = ExtractNode( indexOf_Text, buffer );
// now traverse the node as you please
foreach ( XmlNode node in nextMiNode.ChildNodes[1].ChildNodes )
{
if ( node.Name == "mts" )
{
// Good stuff ?
if ( node.InnerText == "Good stuff" )
Console.WriteLine( node.InnerText );
}
}
Console.ReadKey();
}
static XmlDocument ExtractNode(int indexOf_Text, string buffer)
{
XmlDocument xDoc = new XmlDocument();
StringBuilder sbNode = new StringBuilder();
sbNode.Append( "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
bool inNode = false;
for ( int i = indexOf_Text; i < buffer.Length - 1; i++ )
{
// find the first "<mi>" tag ..
if ( !inNode &&
( buffer[i] == '<' &&
i + 3 < buffer.Length - 1 &&
buffer[i + 1] == 'm' &&
buffer[i + 2] == 'i' &&
buffer[i + 3] == '>' ) )
inNode = true;
if ( inNode ) // capture it
sbNode.Append( buffer[i] );
// find the next "<mi/>" ending tag (only if we found the begining tag : inNode=true)
if ( inNode &&
( buffer[i] == '>' &&
i - 4 >= indexOf_Text &&
buffer[i - 1] == 'i' &&
buffer[i - 2] == 'm' &&
buffer[i - 3] == '/' &&
buffer[i - 4] == '<' ) )
{
break; // we are done
}
}
xDoc.LoadXml( sbNode.ToString() );
return xDoc;
}
}
XElement doc = XElement.Parse(@"<?xml version=""1.0"" encoding=""ISO-8859-1""?><mdc><ne><neun>ADB</neun><nn>SubNetwork=Context</nn><nw>R33</nw><mi><nut>20140101</nut><hq>000</hq><nw><npid>Text to Find</npid><r>0</r></nw></mi></ne><ofid><ofun>ABC</ofun><ofdn>Blah</ofdn><ofsw>18R</ofsw></ofid><mi><mts>More Blah</mts><gp>000</gp><mu>Value1</mu><mu>Value2</mu><mu>Value3</mu><mu>Value4</mu><mu>Value5</mu><nw><npid>ABC1221</npid><r>99</r><r>0</r><r>0</r><r>0</r><r>0</r></nw><nw><npid>ABC1222</npid><r>99</r><r>0</r><r>0</r><r>0</r><r>0</r></nw><nw><npid>ABC1223</npid><r>99</r><r>0</r><r>0</r><r>0</r><r>0</r></nw></mi></mdc>");
IEnumerable<XElement> query1 = doc.Descendants("npid").Where(c => c.Value == "Text to Find").Ancestors("mi");
IEnumerable<XElement> query2 = query1.First().Parent.ElementsAfterSelf("mi");
dynamic resut_node = new XElement("result");
resut_node.Add(query1.First());
resut_node.Add(query2.First());
Console.Write(resut_node.ToString());
XElement doc = XElement.Parse(@"<?xml version=""1.0"" encoding=""ISO-8859-1""?>
<mdc>
<ne>
<neun>ADB</neun>
<nn>SubNetwork=Context</nn>
<nw>R33</nw>
<mi>
<nut>20140101</nut>
<hq>000</hq>
<nw>
<npid>Text to Find</npid>
<r>0</r>
</nw>
</mi>
</ne>
<ofid>
<ofun>ABC</ofun>
<ofdn>Blah</ofdn>
<ofsw>18R</ofsw>
</ofid>
<NodeToExtract>
<mts>More Blah</mts>
<gp>000</gp>
<mu>Value1</mu>
<mu>Value2</mu>
<mu>Value3</mu>
<mu>Value4</mu>
<mu>Value5</mu>
<nw>
<npid>ABC1221</npid>
<r>99</r>
<r>0</r>
<r>0</r>
<r>0</r>
<r>0</r>
</nw>
<nw>
<npid>ABC1222</npid>
<r>99</r>
<r>0</r>
<r>0</r>
<r>0</r>
<r>0</r>
</nw>
<nw>
<npid>ABC1223</npid>
<r>99</r>
<r>0</r>
<r>0</r>
<r>0</r>
<r>0</r>
</nw>
</NodeToExtract>
</mdc>");
IEnumerable<XElement> query1 = doc.Descendants("npid").Where(c => c.Value == "Text to Find").Ancestors("mi");
IEnumerable<XElement> query2 = query1.First().Parent.ElementsAfterSelf("NodeToExtract");
Console.Write(query2.First().ToString());