0

I try to explain my problem:

Okay, I need the KSCHL and the Info. I need the KSCHL from the result file and then I want to search after the KSCHL in the other file "Data".

In the first file I have all KSCHL.

var kschlResultList = docResult.SelectNodes(...);
var kschlDataList = docData.SelectNodes(...);
var infoDataList = docData.SelectNodes(...);

for (int i = 0; i < kschlResultList.Count; i++)
{
    string kschlResult = kschlResultList[i].InnerText;

    for (int x = 0; x < kschlDataList.Count; x++)
    {
        string kschlData = kschlDataList[x].InnerText;

        if (kschlData == kschlResult)
        {
            for (int y = 0; y < infoDataList.Count; y++)
            {
                string infoData = infoDataList[y].InnerText;

                if (infoData == kschlResult)
                {   
                    //I know the If is false 
                    string infoFromKschl = infoData;
                }
            }
        }
    }
}

The problem is now to find the KSCHL (from the first file) in the second file and then to search after the "info".

So if I have the KSCHL "KVZ1" in the first file, then I want to search this KSCHL in the second file and the associated Info for it.

Hope you understand :)

  • I think I mostly understand :) Have you seen this: https://stackoverflow.com/questions/17040254/how-to-select-a-node-using-xpath-if-sibling-node-has-a-specific-value – Mike M Jan 31 '18 at 12:08
  • ah thanks, so you mean to put this `//a[bb/text() = "zz"]/cc/text()` in the if ? –  Jan 31 '18 at 12:16
  • well, you'd better use the nodes in your xml...... you have an XPath using PricingProcedure and KSCHL and Info. Can you see how you could use those the same way as that link uses ? – Mike M Jan 31 '18 at 12:18
  • hm something like //PricingProcedure[KSCHL/text() = "?"]/Info/text() ..? –  Jan 31 '18 at 12:23
  • yeah :) You don't need to loop...... you can use SelectNodes to get what you want. – Mike M Jan 31 '18 at 12:24
  • yeah, but the XML file is big, like 100.000 lines, and the "PricingProcedure" is there like 100.000 times with many KSCHL's. So I have to loop for all of them, or not? –  Jan 31 '18 at 12:28
  • you might be looping through the results to use them, but you can make your life easier staying "inside" the xml longer. Maybe can you tell more about what the final result looks like? Are you saying you need to merge the xml together? What is the result? Another xml or ...... ? – Mike M Jan 31 '18 at 12:30
  • @MikeM okay, my final result should be a program, like a digital receipt, which can give me the KSCHL and the associated Info for it. Not as XML. So I just need the 2 elements of the file. With the first loop, I have all KSCHLS needed. And now I want the Info from the other file. –  Jan 31 '18 at 12:35
  • Sure. I also mean that "Info from the other file" ...... what should that result be? – Mike M Jan 31 '18 at 12:42
  • @MikeM Ah, ehm if the KSCHL is "KVZ1" and I found this in the second file, then the info just say the meaning of KVZ1, for example the "sales tax". So Kschl = KVZ1 and Info = Sales Tax. And for every KSCHL another info is necesarry. :) –  Jan 31 '18 at 12:48
  • Ok..... so I'm not totally clear on how you'll use the INFO data...... I'll put an answer where I just stick it in a SortedDictionary. – Mike M Jan 31 '18 at 13:01
  • @MikeM so the program should just select different elements from a XML. The using is just for myself, to see how the price is composed. And as I said, my program gives me all "infos", but I only need the specific ones. –  Jan 31 '18 at 13:10
  • Sure..... check it out. The last question would be if you can have more than one INFO for each KSCHL. I assumed only one for the Answer right now. – Mike M Jan 31 '18 at 13:11

1 Answers1

0

You don't have to loop quite so much. :-)

Using XPath - the special strings inside SelectNodes() or SelectSingleNode(), you can go pretty directly to what you want.

You can see a great basic example - several really - of how to select an XML node based on another node at the same level here:
How to select a node using XPath if sibling node has a specific value?

In your case, we can get to a list of the INFO values more simply by looping just through the KSCHL values. I use them as text, because I want to make a new XPath string with them.

I'm not clear exactly what format you want the results in, so I'm simply pushing them into a SortedDictionary for now.

At that last step, you could do other things as is most useful to you..... such as push them into a database, dump them in a file, send them to another function.

    /***************************************************************
     *I'm not sure how you want to use the results still, 
     *  so I'll just stick them in a Dictionary for this example.
     *  ***********************************************************/
    SortedDictionary<string, string> objLookupResults = new SortedDictionary<string, string>();

    // --- note how I added  /text()... doesn't change much, but being specific  <<<<<<
    var kschlResultList = docresult.SelectNodes("//root/CalculationLogCompact/CalculationLogRowCompact/KSCHL/text()");

    foreach (System.Xml.XmlText objNextTextNode in kschlResultList) {

        // get the actual text from the XML text node
        string strNextKSCHL = objNextTextNode.InnerText;

        // use it to make the XPath to get the INFO  ---  see the [KSCHL/text()= ...
        string strNextXPath = "//SNW5_Pricing_JKV-Q10_full/PricingProcedure[KSCHL/text()=\"" + strNextKSCHL + "\" and PRICE>0]/INFO/text()";

        // and get that INFO text!  I use SelectSingleNode here, assuming only one INFO for each KSCHL.....  if there can be more than one INFO for each KSCHL, then we'd need another loop here
        string strNextINFO = docdata.SelectSingleNode(strNextXPath)?.InnerText;  // <<< note I added the ? because now there may be no result with the rule PRICE>0.


        // --- then you need to put this result somewhere useful to you.
        //      I'm not sure what that is, so I'll stick it in the Dictionary object.  
        if (strNextINFO != null) {
            objLookupResults.Add(strNextKSCHL, strNextINFO);
        }

    }
Mike M
  • 1,382
  • 11
  • 23
  • Thank you! I will try this. And I only have one Info for each Kschl. :) –  Jan 31 '18 at 13:21
  • It works! Thank you!! :)) Just one more question, if I also want to put the price to the other things (KSCHL, Info, Price) can I say `int price = docresult.SelectNodes("//root/CalculationLogCompact/CalculationLogRowCompact/Calculated/text()");` ? –  Jan 31 '18 at 13:44
  • Yes, you can pull other criteria from the first XML by changing "KSCHL" to a different XML node name. In this example. you would also need to change the line strNextXPath....... it says "[KSCHL/text() = " . Of course that would have to change to fit the new XML node name. --- or you could also change that into a variable :-) . – Mike M Jan 31 '18 at 14:00
  • Instead of kschlResultList, what if it was criterionResultList..... and we have some kind of strCriteronNodeName variable...... you start putting that strCriterionNodeName in all the XPath strings, rather than the hardcoded "KSCHL" – Mike M Jan 31 '18 at 14:02
  • But then you might need that extra loop -- can some things have the same Price, for example. – Mike M Jan 31 '18 at 14:09
  • ahh okay, yeah and another condition is, that the price have to be over 0, because there are many without price, respectively with 0. And I only need those who are over 0. –  Jan 31 '18 at 14:30
  • You can have more than one test inside the [ ] in your XPath. I'll update the answer to show you... – Mike M Jan 31 '18 at 14:39
  • So I assumed a PRICE node also in docdata...... if that's not quite right, you can do the same thing another place. – Mike M Jan 31 '18 at 14:46
  • Thanks for your help :) But the Price is in the docresult, not the Data, but guess I just put another string/int with Price after the string strNextINFO? –  Feb 01 '18 at 07:25
  • If you want to only get KSCHL with a certain price, such as >0, you can put the [PRICE>0] in that first XPath...... you can put these rules and limits in any XPath. – Mike M Feb 01 '18 at 07:31
  • Okay, so do I need the "and" in the first XPath then? –  Feb 01 '18 at 08:35
  • If you want to only get KSCHL when Price>0, that would work very well. – Mike M Feb 01 '18 at 10:24
  • Allright, and if I want to give all these components out in a DataGridView in WinForms, can the price be an extra column? Sorry I never worked with DataGridView before, its quite confusing. –  Feb 01 '18 at 11:50
  • ah, so that's how you want to use the information :-)..... display in a DataGridView. Of course, you can make it happen. You might want to go about it in a different way. I'm not very familiar with DataGridView myself, but I could recommend this: 1) look at what data objects normally fill a DataGridView ; 2) how can you query xml to populate those objects. It might involve XPath, but maybe some different classes that can fill the data objects. If you search here on SO, I bet you can find examples. – Mike M Feb 01 '18 at 22:56
  • :) -- indeed... lots of hits on SO: https://www.google.com/search?q=c%23+populate+a+datagridview+from+xml+site:stackoverflow.com – Mike M Feb 01 '18 at 22:59
  • Thank you :) So, but I need to write an extra `int price` because I want to have the price too. But when I try to fill the int it says "Error CS0029 Cannot implicitly convert type 'System.Xml.XmlNodeList' to 'int'". So I guess I need something different when I use an int? –  Feb 05 '18 at 08:21
  • What do you think is different from what I did? I can guess one thing. What function did I call to populate the string "strNextInfo" ? – Mike M Feb 05 '18 at 08:48
  • okay now I have `var pathPrice = "//root/CalculationLogCompact/CalculationLogRowCompact/Errechnet/text()"; int nextPrice = Convert.ToInt32(docResult.SelectSingleNode(pathPrice).InnerText);` ? –  Feb 05 '18 at 13:04
  • That sounds better :-). The Inner Text of one single node can be converted to String or Int; a Node List cannot. Did it work? You can always try it! – Mike M Feb 05 '18 at 13:07
  • ahh that make sense! :-)) yeah it works! But in my DataGridView nothing shows up.. It makes 9 lines (for 9 KSCHL ..) but without content, thats so frustrating sometimes :D –  Feb 05 '18 at 13:26
  • If it's a real problem, you can always ask another question in SO. Lots of people use DataGridView's. – Mike M Feb 05 '18 at 13:28
  • yeah, I will try it alone, and if its absolutely not work, I will ask. but thank you for your help :-) –  Feb 05 '18 at 13:41