I know there are a bunch of ways of doing this, but I'm looking for the easiest way of doing it without having to use a streamreader or something more manual that will force me to loop through the whole file and compare endless strings. A possibility would be to use a streamreader to find a specific text, and then use some XML library to retrieve the node.

Here's my XML. This is what I would need to do:

1) find the first instance of tag npid with text Text to Find

2) Extract the node NodeToExtract and store it in some data object. There are several nodes called NodeToExtract but I just want the first one after the initial search of text Text to Find

<?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>

Any help is appreciated.

有帮助吗?

解决方案

Try this out (assuming you mean mi elements by saying NodeToExtract):

    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());

UPDATE

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());

其他提示

The real issue is that there is no way to do this without brute force. One can extract the node in question and then load it into an xmldocument,

for example:

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;
    }
} 
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top