使用 XDocument 创建模式有序 XML

发布于 2024-09-24 01:39:40 字数 1921 浏览 3 评论 0原文

我目前正在尝试找到一种按架构顺序向现有 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 元素中的特定位置,而不仅仅是最后一个子元素,当然,这不像在前面的元素,因为我只有不到 100 个可选元素,这些元素可能在也可能不在 xml 中。

我尝试使用 验证方法将架构验证信息集嵌入到 XDocument 中,我认为这可能会起作用,但它似乎对元素插入位置没有影响。

有办法做到这一点还是我运气不好?

I'm currently trying to find a way of adding some extra elements to existing xml documents in schema order.

The xml has a schema attached to it but I've been unable to find a way to get XDocument manipulations to conform to the schema order.

Example schema extract

<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>

Example xml input

<?xml version="1.0" encoding="utf-8" ?>
<someDocument xmlns="urn:Test">
  <control>
    <applicationId>19</applicationId>
    <dateCreated>2010-09-18</dateCreated>
  </control>
  <body />
</someDocument>

Example code segment

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);

I need to add the OriginalProcId and requestId elements, but they need to go to specific locations in the Control element, not just as last children, Of course its not as easy as doing an AddAfterSelf on the previous element as I have just shy of 100 optional elements that may or may not be in the xml.

I've tried using the Validate method to embed the schema validation info set into the XDocument and I thought that might do the trick but it didn't seem to have an effect on the element insertion location.

Is there a way to do this or am I out of luck?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

新雨望断虹 2024-10-01 01:39:40

我最终用一些 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()));

I ended up doing this with some xlst that transformed the node to itself but ordered, here is the code

// 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()));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文