我目前正在尝试找到一种以架构顺序向现有xml文档添加一些额外元素的方法。
xml附加了一个模式,但我一直无法找到一种方法来使XDocument操作符合模式顺序。
示例模式提取
<xs:element name="control" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="applicationId" type="xs:unsignedByte" minOccurs="1" maxOccurs="1" />
<xs:element name="originalProcId" type="xs:unsignedByte" minOccurs="0" maxOccurs="1" />
<xs:element name="dateCreated" type="xs:date" minOccurs="0" maxOccurs="1" />
<xs:element name="requestId" type="xs:string" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
示例xml输入
<?xml version="1.0" encoding="utf-8" ?>
<someDocument xmlns="urn:Test">
<control>
<applicationId>19</applicationId>
<dateCreated>2010-09-18</dateCreated>
</control>
<body />
</someDocument>
示例代码段
XDocument requestDoc = XDocument.Load("control.xml");
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("urn:MarksTest", XmlReader.Create("body.xsd"));
// Valid according to the schema
requestDoc.Validate(schemas, null, true);
XElement controlBlock = requestDoc.Descendants("control").First();
controlBlock.Add(new XElement("originalProcId", "2"));
controlBlock.Add(new XElement("requestId", "TestRequestId"));
// Not so valid
controlBlock.Validate(controlBlock.GetSchemaInfo().SchemaElement, schemas, null, true);
我需要添加OriginalProcId和requestId元素,但是它们需要转到Control元素中的特定位置,而不仅仅是作为最后一个子元素。当然,这不像在前一个元素上执行AddAfterSelf那么容易,因为我只是害羞的100个可选元素,可能是也可能不在xml中。
我已经尝试使用Validate method将架构验证信息集嵌入到XDocument中,我认为这可能会起到作用,但它似乎对元素插入位置没有影响。
有办法做到这一点还是我运气不好?
答案 0 :(得分:0)
我最终用一些xlst做了这个,它将节点转换为自己但是有序,这里是代码
// Create a reader for the existing control block
var controlReader = controlBlock.CreateReader();
// Create the writer for the new control block
XmlWriterSettings settings = new XmlWriterSettings {
ConformanceLevel = ConformanceLevel.Fragment, Indent = false, OmitXmlDeclaration = false };
StringBuilder sb = new StringBuilder();
var xw = XmlWriter.Create(sb, settings);
// Load the style sheet from the assembly
Stream transform = Assembly.GetExecutingAssembly().GetManifestResourceStream("ControlBlock.xslt");
XmlReader xr = XmlReader.Create(transform);
// Load the style sheet into the XslCompiledTransform
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(xr);
// Execute the transform
xslt.Transform(controlReader, xw);
// Swap the old control element for the new one
controlBlock.ReplaceWith(XElement.Parse(sb.ToString()));