1

I am trying to make some additions to an XML file. I am adding the XML in one format (Format2 below) and would like to transform it to another (Format1 below). How can I do that?

Details:

I have an template.xml which I use to create file so I can import it to a special application which only takes xml by updating the existing attributes. However, depending on some cases more elements and attributes need to be added.

A simplified example of the XML is as follows:

<?xml version="1.0"?>
<chssystem ExportDate="2/21/2018" ExportTime="2:57 PM EST" DateFormat="MM/dd/yyyy" NumberFormat="HH:mm:ss " SchemaValidation="true" ExportVersion="2016.1.SP1710.57" xmlns="http://www.mentor.com/harness/Schema/LibrarySchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mentor.com/harness/Schema/LibrarySchema file:/C:/MentorGraphics/VeSys_Client/dtd/LibrarySchema.xsd" XMLVersion="1.6">

  <librarycomponenttype librarycomponenttype_id="_GROUPID_CONNECTOR" description="Connector" clipgromident="" typecode="CONN" />

  <connectorpart libraryobject_id="_OID_CTEST"  depth="0.0" description="TEST DATA" graphics="0" groupname="Connector" librarycomponenttype_id="_GROUPID_CONNECTOR"  cavityqt="1"  partnumber="CONN-C-TEST"   unitofmeasure="Each"  >
        <librarycavity librarycavity_id="ID1" ca_mappingtype="Userdefined" ca_attach=" " isblocked="1" pingraphic=" " cavityname="1" librarypincontainer_id="_OID_CTEST" sortorder="1"/>
  </connectorpart>

</chssystem>

Let's say I want to add this Format1

<subsystem name="hahaha" 
tag1="NoNo"tag2="SoNo" />

Here is the c# code I am using to create this element:

XmlElement subsystem = xmlDoc.CreateElement("subsystem");

XmlElement name= xmlDoc.CreateElement("name");
name.InnerText = "hahaha";

XmlElement tag1= xmlDoc.CreateElement("tag1");
tag1.InnerText = "NoNo";

XmlElement tag2= xmlDoc.CreateElement("tag2");
tag2.InnerText = "SoNo";

After I append them, I have a new XML with the following Format2

<subsystem xmlns="">
  <name>hahaha</name>
  <tag1>NoNo</tag1>
  <tag2>SoNo</tag2>
</subsystem >

So the C# code adds the extra xmlns=""

The application still returns error in both case with or without the extra xmlns=""

If I manually adjust the data to Format1, there is no error ~~~~> If I can transform the Format2 to Format1, I think the application will accept the xml

The error from an application: In case I keep the xmlns="", error message is Invalid content was found starting with element subsystem, the element name is needed

In case I remove the xmlns="", error message is element name must appear on subsystem, element tag1 must appear on subsystem, element tag2 must appear on subsystem

dbc
  • 104,963
  • 20
  • 228
  • 340
Secret
  • 337
  • 4
  • 11
  • Is `` the root element of your `XmlDocument`? Most likely it isn't and the root element belongs to some XML namespace. Since `` isn't in a namespace, `XmlWriter` adds `xmlns=""` to indicate this. But we need to see a [mcve] to be sure. – dbc Feb 21 '18 at 19:22
  • I made the example to be simple and forgot to change the element name's. In this case it is `subsystem` but the root is `system`. The issue is that if I use the `Format1` there is no issue. I *manually* changed. – Secret Feb 21 '18 at 19:26
  • Then, can you share a [mcve] that includes a sample `template.xml`? – dbc Feb 21 '18 at 19:33
  • Aren't you sort of rewriting your own XSLT, why? – Ismail Hawayel Feb 21 '18 at 19:47
  • @IsmailHawayel, I have limited knowledge in programming so sometimes I am not sure if I take the best approach but I always try to develop something useful. If I want to develop something, I will do some research and start to do something with my findings (but sometimes, it may not be the best approach) – Secret Feb 21 '18 at 20:22
  • @dbc http://s000.tinyupload.com/index.php?file_id=06187142694048218400 - This is the most simplest one and I just wanted to add the `librarycavity ` (which can be 50 of them with different values for attributes) – Secret Feb 21 '18 at 20:29
  • @UlinkSecret so what you are doing here is you have a template and a data source, you fill in the template to create an xml document. in xslt world, the template is an xsl file that will have the final structure and is linked to the source by xpath to data. Transformation would be something like result = template.transform(data), for more info:https://www.codeproject.com/Articles/87621/Introduction-to-XML-and-XSLT-in-Csharp-NET – Ismail Hawayel Feb 21 '18 at 20:48
  • I am trying to understand what is going wrong because there should not be any different between Format1 and Format2 – Secret Feb 21 '18 at 22:40

1 Answers1

1

You have two basic problems here.

Firstly, you are creating name, tag1 and tag2 as child XML elements when you should be creating them as XML attributes. I.e. the two XML fragments below are not equivalent, because <name>hahaha</name> in the first is an element, while name="hahaha" is not:

<subsystem>
  <name>hahaha</name>
</subsystem>

<subsystem name="hahaha" />

In your current code you are creating elements but you should be creating XmlAttribute objects instead, e.g. with XmlDocument.CreateAttribute().

(For an overview of the difference between elements and attributes, see e.g. XSD: difference between Element and Attribute or XML attribute vs XML element.)

Secondly, you are creating your <subsystem> node in the empty namespace by using XmlDocument.CreateElement(string qualifiedName). However, the root element <chssystem> belongs to the "http://www.mentor.com/harness/Schema/LibrarySchema" namespace, thanks to the presence of the xmlns="http://www.mentor.com/harness/Schema/LibrarySchema" attribute. Thus you need to create your <subsystem> node in the same namespace, e.g. with XmlDocument.CreateElement(String qualifiedName, String namespaceURI).

(For an overview of XML namespaces see e.g. What are XML namespaces for?.)

The fix for both these problems is to modify your code to create the <subsystem> correctly, rather than create it wrongly and try to transform it. The following code should do the job:

// Get the XML namespace of the root element.
var namespaceURI = xmlDoc.DocumentElement.NamespaceURI;

// Create the subsystem in the same XML namespace
var subsystem = xmlDoc.DocumentElement.AppendChild(xmlDoc.CreateElement("subsystem", namespaceURI));

// Add the specified attributes.
subsystem.Attributes.Append(xmlDoc.CreateAttributeWithValue("name", "hahaha"));
subsystem.Attributes.Append(xmlDoc.CreateAttributeWithValue("tag1", "NoNo"));
subsystem.Attributes.Append(xmlDoc.CreateAttributeWithValue("tag2", "SoNo"));

It uses the extension method:

public static class XmlNodeExtensions
{
    public static XmlAttribute CreateAttributeWithValue(this XmlDocument doc, string name, string value)
    {
        var attr = doc.CreateAttribute(name);
        attr.Value = value;
        return attr;
    }
}

And generates the following XML:

<chssystem ExportDate="2/21/2018" ExportTime="2:57 PM EST" DateFormat="MM/dd/yyyy" NumberFormat="HH:mm:ss " SchemaValidation="true" ExportVersion="2016.1.SP1710.57" xmlns="http://www.mentor.com/harness/Schema/LibrarySchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mentor.com/harness/Schema/LibrarySchema file:/C:/MentorGraphics/VeSys_Client/dtd/LibrarySchema.xsd" XMLVersion="1.6">
  <librarycomponenttype librarycomponenttype_id="_GROUPID_CONNECTOR" description="Connector" clipgromident="" typecode="CONN" />
  <connectorpart libraryobject_id="_OID_CTEST" depth="0.0" description="TEST DATA" graphics="0" groupname="Connector" librarycomponenttype_id="_GROUPID_CONNECTOR" cavityqt="1" partnumber="CONN-C-TEST" unitofmeasure="Each">
    <librarycavity librarycavity_id="ID1" ca_mappingtype="Userdefined" ca_attach=" " isblocked="1" pingraphic=" " cavityname="1" librarypincontainer_id="_OID_CTEST" sortorder="1" />
  </connectorpart>
  <subsystem name="hahaha" tag1="NoNo" tag2="SoNo" />
</chssystem>

Sample working .Net fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • thank you very much - I just fixed my problem by doing the bad thing:read the file and adjusting the data by replacing the text. I will adjust my code to include your solution. – Secret Feb 22 '18 at 00:01