1

I want to split xml file by tags with attributes into multiple files.

Here is my xml:

Source XML document

<BATCH ID="131070" Date_Submitted="12/1/2014 7:36:06 AM" Date_Received="12/1/2014 7:36:06 AM" Date_Processed="12/1/2014 7:40:00 AM" UserID="PAYPINST" Error_Count="1">
  <CLAIMS Submitter="541884924" Submitter_Num="" Version="005010X223A2">
   <CLAIM Rec_ID="1" Claim_Type="Institutional" Submitter="541884924">

   </CLAIM>
   <CLAIM Rec_ID="2" Claim_Type="Institutional" Submitter="541884924">

   </CLAIM>
 </CLAIMS>
</BATCH>

Here I want to split the file by CLAIM. I have used following code.

            XDocument doc = XDocument.Load(xmlFilePath);
            var newDocs = doc.Descendants("CLAIM")
                             .Select(d => new XDocument(new XElement("BATCH", new XElement("CLAIMS", d))));

            foreach (var newDoc in newDocs)
            {
                newDoc.Save(SplitedxmlFileName);
            }

When I run the code it gives me splited file. But it doesn't give me the attributes of tag.

I refer this link :How to Split an XML file into multiple XML Files

I want output something like this:

Should split to two xml documents as below

1)

<BATCH ID="131070" Date_Submitted="12/1/2014 7:36:06 AM" Date_Received="12/1/2014 7:36:06 AM" Date_Processed="12/1/2014 7:40:00 AM" UserID="PAYPINST" Error_Count="1">
  <CLAIMS Submitter="541884924" Submitter_Num="" Version="005010X223A2">
    <CLAIM Rec_ID="1" Claim_Type="Institutional" Submitter="54188424">

    </CLAIM>
  </CLAIMS>
</BATCH>

2)

<BATCH ID="131070" Date_Submitted="12/1/2014 7:36:06 AM" Date_Received="12/1/2014 7:36:06 AM" Date_Processed="12/1/2014 7:40:00 AM" UserID="PAYPINST" Error_Count="1">
  <CLAIMS Submitter="541884924" Submitter_Num="" Version="005010X223A2">
    <CLAIM Rec_ID="2" Claim_Type="Institutional" Submitter="51884924">

    </CLAIM>
  </CLAIMS>
</BATCH>

How can I split the xml file by tags with attributes?

Community
  • 1
  • 1
Ajay
  • 6,418
  • 18
  • 79
  • 130

1 Answers1

1

I have tried to segregate the steps. You were able to distinguish between different nodes. So you just need the Parent Node Attributes. Assuming that the attribute values of BATCH & CLAIMS will always be same for each and every xml file. You can try the below modification of your code.

XDocument doc = XDocument.Load("XMLFile1.xml");
var newDocs = doc.Descendants("CLAIM")
                         .Select(d => new XDocument(new XElement("BATCH", new XElement("CLAIMS", d))));

var batch = doc.Element("BATCH");
var claims = doc.Descendants("CLAIMS");

int i = 0;
foreach (var newDoc in newDocs)
{
    foreach (XAttribute xat in batch.Attributes())
    {
        newDoc.Element("BATCH").SetAttributeValue(xat.Name, xat.Value);
    }
    foreach (XElement claim in claims)
    {
        foreach (XAttribute xat in claim.Attributes())
        {
            newDoc.Descendants("CLAIMS").ElementAt(0).SetAttributeValue(xat.Name, xat.Value);
        }
    }

    newDoc.Save(i.ToString());
    ++i;
}

Let me know, if it's of any help.

EDIT

XDocument doc = XDocument.Load("XMLFile1.xml");
var newDocs = doc.Descendants("CLAIM")
                         .Select(d => new XDocument(new XElement("BATCH", new XElement("CLAIMS", d))));

var batch = doc.Element("BATCH");
var claims = doc.Descendants("CLAIMS");

int i = 0;
foreach (var newDoc in newDocs)
{
    batch.Attributes().All(p => { newDoc.Element("BATCH").SetAttributeValue(p.Name, p.Value); return true; });

    claims.All(p => p.Attributes().All(k => { newDoc.Descendants("CLAIMS").ElementAt(0).SetAttributeValue(k.Name, k.Value); return true; }));

    newDoc.Save(i.ToString());
    ++i;
}
Piyush
  • 830
  • 8
  • 19
  • Thank you for reply. It works !! But I want to ask one thing is there any other way to do it without loop through the **attributes**? – Ajay Dec 09 '14 at 08:54
  • Hi @AjayPunekar check my edit. We can always remove the loops using linq. It's just loops are easy for understanding. Hence I always prefer them first... – Piyush Dec 09 '14 at 09:42