0

Im wondering how to select a specific element from the heirarchy so that I can format its text.

In the example below I would like to format the specific element to remove the time portion of the date, but I am also looking for a way to format any of the elements for example to add a currency symbol to the text between each price tag.

My example

<orders>
  <order>
    <type> tools </type> //I would like the ability to select this element
    <text> screwdriver </text>
    <id> 100981 </id>
    <price> 5.00 </price>
    <date> 01/01/15 12:51:36 </date>
 </order>

  <order>
    <type> uniform </type>
    <text> boots </text>
    <id> 100546 </id>
    <price> 25.00 </price>
    <date> 12/01/15 15:30:41 </date>
  </order>
</orders>

What I have so far

foreach (XElement element in doc.Descendants())
{
    var nodes = element.Nodes().Where(p => p.NodeType == XmlNodeType.Text);

    foreach (XText node in nodes)
    {
      node.Value = FirstLetterToUpper( node.Value );// set the first letter of each output to be uppercase
     }
}

What I have tried

foreach (XElement element in doc.Descendants())
{
    var nodes = element.Nodes().Where(p => p.NodeType == XmlNodeType.Text);

    if( element.Descendants() == element.Element("date"))
    {
         element.Value = Convert.ToDateTime(element.Value).ToShortDateString();
    }

    foreach (XText node in nodes)
    {
      node.Value = FirstLetterToUpper( node.Value );
    }
}

I have some XML experience but have never worked with XElement before.

I've been searching SO for a while now but cant find what Im looking for. The answers below are some of the suggested answers from typing this question but they dont provide a solution as the XML elements are generated dynamically in a loop.

XElement node with text node has its formatting ignored

string.Format in XElement not formatting

Any help with this would be great as I have not attempted this before. Thanks.

Community
  • 1
  • 1
Master Yoda
  • 4,334
  • 10
  • 43
  • 77

2 Answers2

2

You can get the text node's parent using Parent property and check it's name:

foreach (XText node in doc.DescendantNodes()
                          .Where(x => NodeType == XmlNodeType.Text))
{
       if(node.Parent.Name == "date") { ... }
       if(node.Parent.Name == "price") { ... }
}

BTW, don't forget the save the document using XDocument.Save method after you made the changes.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
  • This is a very good answer, is it possible to prepend a £ symbol before the price text shown in the example? e.g. £5.00 – Master Yoda Jan 13 '15 at 14:49
  • sure, just use string concatenation or [formatting](http://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx) – Selman Genç Jan 13 '15 at 14:51
  • Thanks for the link, something to familiarize myself with. The linq query was not necessary in this instance but will come in handy in the future im sure. – Master Yoda Jan 13 '15 at 14:56
  • One final question, while you have mentioned the node type above can the nodeType be anything other than text? for example if the date is set as a datetime object? – Master Yoda Jan 13 '15 at 15:28
0

I usually create one class to represent the xml and send yo the instance of object with correct type. for Example convert.ToDecimal(node.innerText)

VhsPiceros
  • 410
  • 1
  • 8
  • 17