Search code examples
c#xmllinqodt

Copy an Xml Attribute with Linq


I have following xml structure with namespaces:

<office:document-content
<office:body>
<office:text text:use-soft-page-breaks="true">
  <text:p text:style-name="Standard">&lt;Text&gt;</text:p>
</office:text>
</office:body>
</office:document-content>

This comes from the content.xml of an unzipped .odt writer file. Now I just want to copy the attribute with the inner text "<Text>" and replace the copy with a new text. I tried this:

    XmlFileOperations xml = new XmlFileOperations();
        XDocument doc = XDocument.Load(Path.Combine(ConfigManager.InputPath, "File", "content.xml"));

        var source = doc.Descendants()
            .Where(e => e.Value == "<Text>")
            .FirstOrDefault();
        var target = new XElement(source);
        target.Add(new XAttribute("Standard", source.Attribute(textLine)));

        doc.Save(Path.Combine(ConfigManager.InputPath, "File", "content.xml"));

This does not work. It tells me that I have a sign in the text which can not be applied to the name. How I can just copy my attribute in this case?

Thank you!

Edit: The result should be

<office:document-content
<office:body>
<office:text text:use-soft-page-breaks="true">
  <text:p text:style-name="Standard">&lt;Text&gt;</text:p>
  <text:p text:style-name="Standard">some new value</text:p>
</office:text>
</office:body>
</office:document-content>

Solution

  • If I understand you correctly, you need the value of <Text> replace with textLine.

    Try this code

    var source = doc.Descendants()
        .Where(e => !e.HasElements && e.Value == "<Text>")
        .FirstOrDefault();
    
    var target = new XElement(source);
    target.Value = textLine;
    source.AddAfterSelf(target);
    
    doc.Save(...);