1

How do I add xml prefixes using XDocument to an existing root element? I have the following XML:

<processSalesOrder>
  <header/>
</processSalesOrder>

and I want it to look like:

<ns0:processSalesOrder xmlns:ns0='https://xyx/'>
  <header/>
</ns0:processSalesOrder>

In my scenario, I am receiving this xml from web api and passing it long to another web service. The web service is expecting a namespace prefix on the root element.

The web service is from a third party software, it is expecting the xml in a certain format. I tried XmlDocument, XDocument etc ... I couldn't find a way to add the namespace prefix only on the root element. Webservice was rejecting the transactions if the prefix was on Descendants.

satish
  • 31
  • 6
  • https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/how-to-create-a-document-with-namespaces-linq-to-xml – SLaks Jul 05 '18 at 22:02
  • It looks like there might be some help here: https://social.msdn.microsoft.com/Forums/en-US/8410bc2a-477f-4efa-a9d4-94ee24972208/need-help-to-add-prefix-for-all-the-elements-in-pipeline-component?forum=biztalkgeneral – Robert Harvey Jul 05 '18 at 22:03
  • @Dijkgraaf Don't bother, you can't get them to understand that. – Johns-305 Jul 06 '18 at 12:32
  • Hi @satish, unfortunately, none of the Answer apply and since it's been wrongly closed as Duplicate, you've hit a dead end. The Answer is BizTalk specific, hence not a Duplicate. You'll have better luck at the BizTalk Forum at MSDN. – Johns-305 Jul 06 '18 at 12:40
  • @Dijkgraaf Not worth it. If your future Answer is 100% correct, accurate and up to their standards the first time, it's like a 10 year ban. – Johns-305 Jul 08 '18 at 11:53

3 Answers3

0

Got Reference from here Developer Name: Vijay Sirigiri

If you are trying to add namespace to the elements after loading the xml document then it is not possible.

From MSDN:

You cannot add, modify, or delete an XML namespace definition in an instance of an XML document after the document has been loaded into the XML Document Object Model (XMLDOM) parser. The XML nodes that are used to represent data in the XML document are created when the document is loaded into the XMLDOM parser. These nodes are permanently bound to their XML namespace attributes when they are created. Therefore, the empty XML namespace declaration (xmlns = "") is appended to the child nodes of these nodes to preserve the default XML namespace attribute of these nodes.

However you can load the input, read each element and write it to another document (or in-memory) which has the namespace set. Below is the code that parses the string xml, creates a new xml element along with namespace prefix and namespace.

            String xmlWithoutNamespace =
                @"<Folio><Node1>Value1</Node1><Node2>Value2</Node2><Node3>Value3</Node3></Folio>";
            String prefix ="vs";
            String testNamespace = "http://www.testnamespace/vs/";
            XmlDocument xmlDocument = new XmlDocument();

            XElement folio = XElement.Parse(xmlWithoutNamespace);
            XmlElement folioNode = xmlDocument.CreateElement(prefix, folio.Name.LocalName, testNamespace);

            var nodes = from node in folio.Elements()
                        select node;

            foreach (XElement item in nodes)
            {
                var node = xmlDocument.CreateElement(prefix, item.Name.ToString(), testNamespace);
                node.InnerText = item.Value;
                folioNode.AppendChild(node);
            }

            xmlDocument.AppendChild(folioNode);

xmlDocument now contains the xml with each node prefixed with vs.

Hitesh Anshani
  • 1,499
  • 9
  • 19
  • As he is trying to do this in BizTalk, I would advice against doing it in custom code like this when it can be done using out of the box BizTalk functionality. Trying to do it in custom code will possibly run into threading issues (as BizTalk multi-threads) and memory usage issues (as the above will load the entire XML document into memory). – Dijkgraaf Jul 06 '18 at 02:12
  • Ohk. @Dijkgraff – Hitesh Anshani Jul 06 '18 at 04:10
0

You're trying to specify an alias for the empty namespace. XDocument doesn't allow that:

The prefix 'ns0' cannot be bound to the empty namespace name.

So no, I don't think you can do this with XDocument. I don't think it is even valid XML to do so - emphasis mine:

[Definition:] If the attribute name matches PrefixedAttName, then the NCName gives the namespace prefix, used to associate element and attribute names with the namespace name in the attribute value in the scope of the element to which the declaration is attached. In such declarations, the namespace name may not be empty.

[Definition:] If the attribute name matches DefaultAttName, then the namespace name in the attribute value is that of the default namespace in the scope of the element to which the declaration is attached. In such a default declaration, the attribute value may be empty. Default namespaces and overriding of declarations are discussed in "5. Applying Namespaces to Elements and Attributes".

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I left it empty in the example, but the webservice is expecting a valid namespace. I am not at work at the moment, but do you think I can load into a new memorystream and add a prefix with a namespace using xml serialization ? – satish Jul 05 '18 at 22:26
  • @satish `but the webservice is expecting a valid namespace` why don't you modify your webservice accordingly instead of making some modifications on xml. It seems like an [XY prbplem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Eser Jul 05 '18 at 22:33
  • I can't make modifications in the webservice, its from a third party. – satish Jul 05 '18 at 22:38
  • 1
    @satish It still seems to be an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) Your *actual* problem is still unclear. – Eser Jul 05 '18 at 22:46
  • Read the post again, if it seems to be an XY Problem. Please ignore the post. – satish Jul 05 '18 at 22:53
  • @satish ah, then yes, this answer won't help you. Tip: using a dummy namespace would have been much better than using the empty one. No, you can't change the namespace of XML without completely rewriting it. The namespace is fundamental to the name. Maybe xslt could help here, as a conversion tool? – Marc Gravell Jul 06 '18 at 07:20
0

As per Roberts comment, you can add the namespace in the Receive Pipeline using a add namespace pipeline component. If you have BizTalk Enterprise and have installed the ESB Toolkit there is an out of the box one called ESB Add Namespace, or you have to write your own Pipeline Component to do this.

The other option is to have two schemas, one without the namespace that you specify in your XML dissasembler component in your Receive Pipeline, another schema with the namespace and you have a map from one to the other. This second schema should have ElementFormDefault set to (Default) or Unqualified if you don't want the namespace prefixes on the Elements. If you are future proofing it, you would also have a canonical/internal schema and map from the source schema to the internal schema on the Receive Port and from the internal to the destination schema on the Send Port.

Dijkgraaf
  • 11,049
  • 17
  • 42
  • 54