I'm trying to add new elements to an existing XDocument where the new XElement either specifies the namespace or is part of the default namespace.
I already have a XmlNamespaceManager and I can select elements using that.
XmlNamespaceManager nsMgr = new XmlNamespaceManager(new NameTable());
nsMgr.AddNamespace("default", "http://www.mismo.org/residential/2009/schemas");
nsMgr.AddNamespace("customNs", "http://custom.org");
Consider the following XML
<ROOT xmlns="http://www.mismo.org/residential/2009/schemas" xmlns:customNs="http://custom.org">
<ELM_1>
<ELM_1_SUB_1>Some value</ELM_1_SUB_1>
</ELM_1>
<customNs:ELM_2>
<customNs:ELM_2_SUB_1>Another value</customNs:ELM_2_SUB_1>
</customNs:ELM_2>
</ROOT>
I'd like to write some code that would result in this:
<ROOT xmlns="http://www.mismo.org/residential/2009/schemas" xmlns:customNs="http://custom.org">
<ELM_1>
<ELM_1_SUB_1>Some value</ELM_1_SUB_1>
<ELM_1_SUB_2>ADDED TO DEFAULT NAMESPACE</ELM_1_SUB_2>
</ELM_1>
<customNs:ELM_2>
<customNs:ELM_2_SUB_1>Another value</customNs:ELM_2_SUB_1>
<customNs:ELM_2_SUB_2>ADDED TO CUSTOM NAMESPACE</customNs:ELM_2_SUB_2>
</customNs:ELM_2>
</ROOT>
I have tried the following:
var elm1 = xDoc.XPathSelectElement("/default:ROOT/default:ELM_1", nsMgr);
elm1.Add(new XElement("default:ELM_1_SUB_2", "ADDED TO DEFAULT NAMESPACE"));
var elm2 = xDoc.XPathSelectElement("/default:ROOT/customNs:ELM_2", nsMgr);
elm2.Add(new XElement("customNs:ELM_2_SUB_2", "ADDED TO CUSTOM NAMESPACE"));
The above code does select the elements I want to add to with no issue but the Add throws an XmlException: The ':' character, hexadecimal value 0x3A, cannot be included in a name..
When I try without the namespace provided in the element name I don't get an error but it doesn't do what I want.
So this:
var elm1 = xDoc.XPathSelectElement("/default:ROOT/default:ELM_1", nsMgr);
elm1.Add(new XElement("ELM_1_SUB_2", "ADDED TO DEFAULT NAMESPACE"));
Results in this:
<ROOT xmlns="http://www.mismo.org/residential/2009/schemas" xmlns:customNs="http://custom.org">
<ELM_1>
<ELM_1_SUB_1>Some value</ELM_1_SUB_1>
<ELM_1_SUB_2 xmlns="">ADDED TO DEFAULT NAMESPACE</ELM_1_SUB_2>
</ELM_1>
<customNs:ELM_2>
<customNs:ELM_2_SUB_1>Another value</customNs:ELM_2_SUB_1>
</customNs:ELM_2>
</ROOT>
What am I missing to create the desired XML output?
Create XNamespace types with the desired values.
Use them when creating an XElement.
XNamespace defaultNs = "http://www.mismo.org/residential/2009/schemas";
XNamespace customNs = "http://custom.org";
elm1.Add(new XElement(defaultNs + "ELM_1_SUB_2", "ADDED TO DEFAULT NAMESPACE"));
elm2.Add(new XElement(customNs + "ELM_2_SUB_2", "ADDED TO CUSTOM NAMESPACE"));
Related
I am trying to get a node in a simple XML, but no matter what I try I always get null.
I am guessing that the issue is the namespace.
I am simply trying to get the value of the ID element, 331377697.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("E:\\0323.xml");
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace("cac", "http://xxxxxx Some URL XXXX");
manager.AddNamespace("cbc", "http://xxxxxx Some URL XXXX");
string query = "/StandardBusinessDocument/Invoice/cbc:ID";
XmlNode xmlNode = xmlDoc.SelectSingleNode(query, manager);
The XML:
<StandardBusinessDocument xmlns="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader">
<StandardBusinessDocumentHeader>
...
</StandardBusinessDocumentHeader>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccts="urn:un:unece:uncefact:documentation:2"
...
</Invoice>
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<cbc:CustomizationID>1234</cbc:CustomizationID>
<cbc:ProfileID>1234564</cbc:ProfileID>
<cbc:ID>331377697</cbc:ID>
<cbc:IssueDate>2017-03-23</cbc:IssueDate>
<cbc:InvoiceTypeCode listID="UNCL1001">380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode listID="ISO4217">NOK</cbc:DocumentCurrencyCode>
<cac:OrderReference>
<cbc:ID>146136</cbc:ID>
</cac:OrderReference>
...
You must specify the exact namespaces.
Also you have to specify namespace prefixes for all elements in the XPath.
manager.AddNamespace("nsDoc", "http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader");
manager.AddNamespace("nsInvoice", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2");
manager.AddNamespace("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2");
string query = "/nsDoc:StandardBusinessDocument/nsInvoice:Invoice/cbc:ID";
It's supposed to work.
I'm trying to write a XML-document programatically.
I need to add <xsd:schema> tag to my document.
Currently I have:
var xmlDoc = new XmlDocument();
var root = xmlDoc.CreateElement("root");
xmlDoc.AppendChild(root);
var xsdSchemaElement = xmlDoc.CreateElement("schema");
xsdSchemaElement.Prefix = "xsd";
xsdSchemaElement.SetAttribute("id", "root");
root.AppendChild(xsdSchemaElement);
However, this renders to:
<root>
<schema id="root" />
</root>
How do I get the tag to be <xsd:schema>?
Already tried var xsdSchemaElement = xmlDoc.CreateElement("xsd:schema"); which simply ignores the xsd:.
Edit #1
Added method
private static XmlSchema GetTheSchema(XmlDocument xmlDoc)
{
var schema = new XmlSchema();
schema.TargetNamespace = "xsd";
return schema;
}
which is called like xmlDoc.Schemas.Add(GetTheSchema(xmlDoc)); but does not generate anything in my target XML.
Using LINQ-to-XML, you can nest XElements and XAttributess in a certain hierarchy to construct an XML document. As for namespace prefix, you can use XNamespace.
Notice that every namespace prefix, such as xsd in your case, has to be declared before it is used, something like xmlns:xsd = "http://www.w3.org/2001/XMLSchema".
XNamespace xsd = "http://www.w3.org/2001/XMLSchema";
var doc =
new XDocument(
//root element
new XElement("root",
//namespace prefix declaration
new XAttribute(XNamespace.Xmlns+"xsd", xsd.ToString()),
//child element xsd:schema
new XElement(xsd + "schema",
//attribute id
new XAttribute("id", "root"))));
Console.WriteLine(doc.ToString());
output :
<root xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:schema id="root" />
</root>
I am using the following code
var xmlFile = fromConfiguration + #"xyz.xml";
XDocument document = XDocument.Load(xmlFile);
var xElement = document.Root;
xElement.Add(new XElement("elementName", "elementText"));
document.Save(xmlFile);
XDocument documentN = XDocument.Load(xmlFile);
XElement element = (from xml2 in documentN.Descendants("elementName")
select xml2).FirstOrDefault();
element.RemoveAttributes();
documentN.Save(xmlFile);
This gives me..
<elementName xmlns="">elementText</elementName>
xmlns is added by default.
Is there any way I can add without xmlns?
<elementName>elementText</elementName>
This is what I need to parse in my xsl file.
ANy help ??
One of the ancestor elements must be setting a default namespace, e.g.
<foo xmlns="http://foo.bar">
<!-- Your element name -->
</foo>
If you want:
<foo xmlns="http://foo.bar">
<elementName>elementText</elementName>
</foo>
... then that means elementName is implicitly in a namespace of http://foo.bar, because the default is inherited. So you should use:
XNamespace ns = "http://foo.bar";
xElement.Add(new XElement(ns + "elementName", "elementText"));
If you might have different namespaces in different files, you could determine the default namespace programmatically - although it may not be the namespace of the root element, e.g.
<other:foo xmlns="http://foo.bar" xmlns:other="http://surprise">
<!-- This is still in http://foo.bar -->
<elementName>elementText</elementName>
</foo>
Usually it is better to learn how to find or select elements in a namespace and how to construct them thus if you do
xElement.Add(new XElement(xElement.Name.Namespace + "elementName", "elementText"));
you don't have the problem of xmlns="''.
I have a xml file like below, i want to find the node which property "name" value equals "ImageListView"
I have writen below code:
var nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1");
xpath = "//asmv1:assembly/dependency/dependentAssembly/assemblyIdentity[name='ImageListView']";
XElement ele = doc.XPathSelectElement(xpath, nsmgr);
ele.Remove();
but cannot find anything. is any wrong here? thanks.
Your XML has default namespace here :
<asmv1:assembly
......
xmlns="urn:schemas-microsoft-com:asm.v2"
......>
Therefore, all XML element without prefix considered in default namespace. You need to add prefix that point to default namespace URI, and use it in XPath :
var nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("asmv1", "urn:schemas-microsoft-com:asm.v1");
nsmgr.AddNamespace("d", "urn:schemas-microsoft-com:asm.v2");
xpath = "//asmv1:assembly/d:dependency/d:dependentAssembly/d:assemblyIdentity[#name='ImageListView']";
XElement ele = doc.XPathSelectElement(xpath, nsmgr);
ele.Remove();
UPDATE :
fixed the XPath slightly. You need to use # to point to attribute : ... [#name='ImageListView']
Using C#2.0 and VIsualStudio2005
I'm trying to access the "DisplayName" inside "MonitorResponseRecord"
from an XML file like the one Below:
<Magellan xsi:schemaLocation="http://tempuri.org/XMLSchema.xsd ..\Schema\Configuration.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
<SchemaVersion>1.0</SchemaVersion>
<MonitorScope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="CleanStationChemicalManifoldFeed5" xmlns="http://tempuri.org/XMLSchema.xsd">
<PersonalSafety>
<MonitorResponseRecord Enabled="true" DisplayName="ChemicalManifoldFeed5ControllerFault">
<ExpressionMonitor>
<Expression>(ChemicalManifold.Feed5.DispenseValve = Open) and ((ChemicalManifold.Feed5.ViolatedRegion = HighProcess) or (ChemicalManifold.Feed5.ViolatedRegion = LowProcess) or (ChemicalManifold.Feed5.ViolatedRegion = Minimum))</Expression>
<TestInterval>0.1</TestInterval>
<MinimumTimeBetweenResponses>5</MinimumTimeBetweenResponses>
</ExpressionMonitor>
<Response>
<PostAlarm>
<AlarmName>ChemicalManifold_Feed5_ControllerFault</AlarmName>
<Parameter1 />
<Parameter2>Alarm Region = {ChemicalManifold.Feed5.ViolatedRegion}</Parameter2>
<Parameter3>{RecipeName}-{StepName}</Parameter3>
<Parameter4>FlowSetpoint = {ChemicalManifold.Feed5.Setpoint}-LPM, ActualFlow = {ChemicalManifold.Feed5.FlowMeter}-LPM</Parameter4>
</PostAlarm>
<ResponseEvent>
<TargetResource />
<Event>PA</Event>
<Reason>ChemicalSupply</Reason>
</ResponseEvent>
</Response>
</MonitorResponseRecord>
</PersonalSafety>
<PersonalSafety>
<MonitorResponseRecord Enabled="true" DisplayName = "PressureValveFailure">
...
...
...and soon
My current C# attempt is as follows, BUT it always hangs up when I try to XmlDocument.Load("");
XmlDocument doc = new XmlDocument();
doc.Load("../UMC0009.Configuration.Root.xml");
string attrVal = doc.SelectSingleNode("MonitorResponseRecord/#DisplayName").Value;
BUUUUT won't work :/ any help out there?
UPDATE:
the exception I recieve is as follows, and occures at the doc.Load("...") line:
{"Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function."} System.Exception {System.Xml.XPath.XPathException}
Your XPath query will be relative to the document root:
doc.SelectSingleNode("MonitorResponseRecord/#DisplayName")
To make it search anywhere in the doc prefix it with double slash:
doc.SelectSingleNode("//MonitorResponseRecord/#DisplayName")
If that still doesn't work I would try the above example after stripping out all those namespace declarations on the two root nodes.
Otherwise, with the namespace declarations you may find you need to define XML namespace mappings and use prefixes in your XPath like:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("x", "http://tempuri.org/XMLSchema.xsd");
doc.SelectSingleNode("//x:MonitorResponseRecord/#DisplayName")
What about:
XmlDocument doc = new XmlDocument();
doc.Load("UMC0009.Configuration.Root.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "http://tempuri.org/XMLSchema.xsd");
string attrVal = doc.SelectSingleNode("//ns:MonitorResponseRecord/#DisplayName", nsmgr).Value;
Using a namespace manager, specify your namespace URI and use it in your XPath.
It works for me.