4

As a follow up to this question I cannot figure out how to remove a period from all of my field names in JSON input.

I am converting XML to JSON and creating a BsonDocument to be inserted into a MongoDB database using the Newtonsoft library like this:

XmlDocument doc = new XmlDocument();
doc.Load(filePath);

String jsonText = JsonConvert.SerializeXmlNode(doc);

BsonDocument = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(jsonText);

I can't insert this because I'll get a serialization exception since the element name contains a period. How can I process through either the JSON string or the BsonDocument to change them?

I have successfully iterated through my document recursively:

private void Print(BsonDocument document)
{
    foreach (BsonElement element in document)
    {
        Console.WriteLine(element.Name);

        if (element.Value.IsBsonDocument)
        {
            Print(element.Value.AsBsonDocument);
        }
        else if (element.Value.IsBsonArray)
        {
            var array = element.Value.AsBsonArray;
            foreach (BsonDocument doc in array)
            {
                Print(doc);
            }
        }
    }
}

However, BsonDocument.Name is not a field I can set, only get. How can I update the BsonDocument or the JSON string to remove the invalid field names?

Community
  • 1
  • 1
AdamMc331
  • 16,492
  • 10
  • 71
  • 133

1 Answers1

2

I dont know enough about your XML/JSON structure but why dont you process the XML before you convert it into JSON and replace the ElementNames? As outlined in this ANSWER?

XmlDocument xmlDoc = new XmlDocument();

        xmlDoc.LoadXml(File.ReadAllText(@"{path}\xml.xml", Encoding.Default));

        XmlNodeList nodeList = xmlDoc.SelectNodes("//*['.' = substring(name(), string-length(name())- string-length('.') +1)]");

        foreach (XmlNode node in nodeList)
        {

            string newName = node.Name.Replace(".", "");
            // create new (renamed) Content node
            XmlNode newNode = xmlDoc.CreateElement(newName);

            newNode.InnerXml = node.InnerXml;

            // replace existing BatteryTest node with newly renamed Content node
            node.ParentNode.InsertBefore(newNode, node);
            node.ParentNode.RemoveChild(node);
        }

        xmlDoc.Save(@"{path}\xml.xml");
Community
  • 1
  • 1
Isaiah4110
  • 9,855
  • 1
  • 40
  • 56
  • I don't see why not. This is not exclusive to the string "BatteryTest." though. How can I modify this to look for any node name with a period? – AdamMc331 Dec 28 '15 at 15:04
  • You will have to replace the Xpath query to use Regex, check the link here: http://www.w3.org/TR/xquery-operators/#regex-syntax. Basically you ca use the Xpath matches function along with the "$" to match the end of the string to get what you want. As for the exact regex/xpath, If you send me the sample XML, I will take a look and update the answer later. – Isaiah4110 Dec 28 '15 at 15:57
  • Updated the answer with the XPath query. Let me know if it solved your issue. – Isaiah4110 Dec 30 '15 at 18:29
  • Did this answer your question? If yes, can you please mark it as the answer? – Isaiah4110 Jan 02 '16 at 04:00
  • I apologize for the lack of response, this is for a project at work and have been in and out due to the holidays. I've given an upvote for your help, but will accept it once I can verify it on Monday. Thank you again! – AdamMc331 Jan 03 '16 at 20:53
  • 1
    All good mate, I was just reminding since sometimes people forget it altogether! – Isaiah4110 Jan 03 '16 at 22:09
  • 1
    Yeah haha, I give more answers than I do ask questions and I see it all the time. What you said seems like it will work, I don't doubt you, but I don't want to accept it for the sake of other people who might stumble upon this in case we need to tweak the answer slightly to really work. – AdamMc331 Jan 03 '16 at 23:20
  • I'm getting an xpath exception: Additional information: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function. I think it's because of the function `name()` inside the xpath. How can I create the Namespace Manager needed here? – AdamMc331 Jan 04 '16 at 16:46
  • can you paste your sample XML above, so that I can check on the namespace manager? – Isaiah4110 Jan 05 '16 at 15:52
  • Here is a gist of what the XML could look like (simplified a bit): https://gist.github.com/AdamMc331/abc234e926ae789575f4 – AdamMc331 Jan 05 '16 at 18:14
  • that doesnt have any namespace info, can you add the root tag as well? – Isaiah4110 Jan 05 '16 at 21:21
  • That flashReportGeneratorAddedTag is the root tag in the xml though? – AdamMc331 Jan 05 '16 at 21:24
  • I was playing around with this, issue is .Net doesnt support xpath 2.0 functions. Let me look around and I will get back tmrw. – Isaiah4110 Jan 05 '16 at 23:43
  • Awesome. I'll see what I can find on it too. – AdamMc331 Jan 06 '16 at 00:27
  • here you go: XmlNodeList nodeList = xmlDoc.SelectNodes("//*['.' = substring(name(), string-length(name())- string-length('.') +1)]"); – Isaiah4110 Jan 06 '16 at 15:44
  • Got a similar answer here, and updated the query for your needs. http://stackoverflow.com/a/3470779/1766402 tested it on my box and it works – Isaiah4110 Jan 06 '16 at 15:45
  • Updated the code in the answer as well, did test it locally with your XML and it works. – Isaiah4110 Jan 06 '16 at 15:59
  • 1
    BEAUTIFUL! I was getting so close but had weird issues, I realized it was the parent node thing and when I came back to tell you you had edited your answer already. Thank you so much! I owe you more rep than I can give in one vote haha. – AdamMc331 Jan 06 '16 at 16:12
  • 1
    I'm going to give you a bounty on this when it lets me in 24 hours haha. You've been helping me for over a week I can't thank you enough. – AdamMc331 Jan 06 '16 at 16:14
  • 2
    Am glad I was able to help :) Am pretty sure you would have done the same. Happy coding! – Isaiah4110 Jan 06 '16 at 18:16
  • 2
    I must say, that was really generous of you to give me that bounty! I have helped many people the way I helped you but no one has ever responded the way you did. – Isaiah4110 Jan 08 '16 at 15:19
  • 2
    Well, I felt bad simply because of the time required and you doing most of the leg work. If it had been something simple that you answered once and it worked I probably wouldn't have, but I definitely appreciate you taking the time to come back and check on it. – AdamMc331 Jan 08 '16 at 15:24