简体   繁体   中英

Add Attribute based on its Parent tag using linq to xml

i have a problem where i need to Add attribute to the element based on its Parent element

here is my input:

<p>
    <InlineEquation ID="IEq4">
        <math xmlns:xlink="http://www.w3.org/1999/xlink">
            <mi>n</mi>
            <mo>!</mo>
        </math>
    </InlineEquation>

    <MoreTag>
        <Equation ID="Equ1">
            <math xmlns:xlink="http://www.w3.org/1999/xlink">
                <mi>n</mi>
                <mo>!</mo>
            </math>
        </Equation>
    </MoreTag>
</p>

and here is my output

<p>
    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
        <mi>n</mi>
        <mo>!</mo>
    </math>
    <MoreTag>
        <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">
            <mi>n</mi>
            <mo>!</mo>
        </math>
    </MoreTag>
</p>

if the parent tag name is InlineEquation its tag name and attribute will be changed to <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">

if the parent tag name is Equation its tag name and attribute will be changed to <math xmlns="http://www.w3.org/1998/Math/MathML" display="inline">

here is my code

XElement rootEquation = XElement.load("myfile.xml")
IEnumerable<XElement> equationFormat =
    from el in rootEquation.Descendants("InlineEquation ").ToList()

    select el;
foreach (XElement el in equationFormat)
{
    Console.WriteLine(el);
    //what code do i need here?
}

You have four things you need to do here:

  • Remove the unused namespace declaration xmlns:xlink="..."
  • Add the display attribute
  • Rename the parent element and its descendants to include the new namespace
  • Remove the parent element and replace with its children

So, taking InlineEquation as an example:

XNamespace mathMl = "http://www.w3.org/1998/Math/MathML";

var doc = XDocument.Parse(xml);

foreach (var equation in doc.Descendants("InlineEquation").ToList())
{
    foreach (var math in equation.Elements("math"))
    {
        math.Attributes().Where(x => x.IsNamespaceDeclaration).Remove();
        math.SetAttributeValue("display", "block");

        foreach (var element in math.DescendantsAndSelf())
        {
            element.Name = mathMl + element.Name.LocalName;
        }               
    }

    equation.ReplaceWith(equation.Nodes());            
}

See this fiddle for a working demo. I'll leave Equation and the refactoring to remove the duplication to you.

You could work directly on math nodes, and check their parents

XNamespace newNs= "http://www.w3.org/1998/Math/MathML";
var xDoc = XDocument.Load(<yourxml>);
var maths = xDoc.Descendants("math").ToList();

foreach (var math in maths){
    //remove old namespace (well, all attributes with this code)
    math.RemoveAttributes();

    //change the namespace
    foreach (var m in math .DescendantsAndSelf())
          m.Name = newNs + m.Name.LocalName;

    //add the display attribute depending on parent
    if (math.Parent.Name == "InlineEquation")
        math.SetAttributeValue("display", "block");

    if (math.Parent.Name == "Equation")
        math.SetAttributeValue("display", "inline");

    //replace parent node by math node
    math.Parent.ReplaceWith(newNode);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM