在现有文档的特定位置插入 XML 节点 [英] Insert XML node at a specific position of an existing document

查看:20
本文介绍了在现有文档的特定位置插入 XML 节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含一些可选节点的现有 XML 文档,我想在某个位置插入一个新节点.

I have an existing XML document with some optional nodes and I want to insert a new node, but at a certain position.

文档看起来像这样:

<root>
  <a>...</a>
  ...
  <r>...</r>
  <t>...</t>
  ...
  <z>...</z>
</root>

新节点(<s>...</s>)应该插入节点<r><t>之间;,产生:

The new node (<s>...</s>) should be inserted between node <r> and <t>, resulting in:

<root>
  <a>...</a>
  ...
  <r>...</r>
  <s>new node</s>
  <t>...</t>
  ...
  <z>...</z>
</root>

问题是,现有节点是可选的.因此,我无法使用 XPath 查找节点 <r> 并在其后插入新节点.

The problem is, that the existing nodes are optional. Therefore, I can't use XPath to find node <r> and insert the new node after it.

我想避免蛮力方法":从 <r> 搜索到 <a> 以找到存在的节点.

I would like to avoid the "brute force method": Search from <r> up to <a> to find a node that exists.

我还想保留顺序,因为 XML 文档必须符合 XML 模式.

I also want to preserve the order, since the XML document has to conform to a XML schema.

可以使用 XSLT 以及普通的 XML 库,但由于我只使用 Saxon-B,因此无法使用模式感知 XSLT 处理.

XSLT as well as normal XML libraries can be used, but since I'm only using Saxon-B, schema aware XSLT processing is not an option.

有人知道如何插入这样的节点吗?

Does anyone have an idea on how to insert such a node?

谢谢,我的钥匙_

推荐答案

[替换我上一个答案.现在我更了解你需要什么了.]

[Replaced my last answer. Now I understand better what you need.]

这是一个 XSLT 2.0 解决方案:

Here's an XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/root">
    <xsl:variable name="elements-after" select="t|u|v|w|x|y|z"/>
    <xsl:copy>
      <xsl:copy-of select="* except $elements-after"/>
      <s>new node</s>
      <xsl:copy-of select="$elements-after"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

您必须明确列出之后的元素或之前的元素.(您不必同时列出两者.)我倾向于选择两个列表中较短的一个(因此在上面的示例中是t"-z",而不是a"-r").

You have to explicitly list either the elements that come after or the elements that come before. (You don't have to list both.) I would tend to choose the shorter of the two lists (hence "t" - "z" in the above example, instead of "a" - "r").

可选增强功能:

这样就完成了工作,但是现在您需要在两个不同的位置(在 XSLT 和模式中)维护元素名称列表.如果它变化很大,那么它们可能会不同步.如果您将新元素添加到模式但忘记将其添加到 XSLT,那么它将不会被复制.如果您担心这一点,您可以实现自己的模式感知.假设您的架构如下所示:

This gets the job done, but now you need to maintain the list of element names in two different places (in the XSLT and in the schema). If it changes much, then they might get out of sync. If you add a new element to the schema but forget to add it to the XSLT, then it won't get copied through. If you're worried about this, you can implement your own sort of schema awareness. Let's say your schema looks like this:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="a" type="xs:string"/>
        <xs:element name="r" type="xs:string"/>
        <xs:element name="s" type="xs:string"/>
        <xs:element name="t" type="xs:string"/>
        <xs:element name="z" type="xs:string"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>

现在您需要做的就是更改 $elements-after 变量的定义:

Now all you need to do is change your definition of the $elements-after variable:

  <xsl:variable name="elements-after" as="element()*">
    <xsl:variable name="root-decl" select="document('root.xsd')/*/xs:element[@name eq 'root']"/>
    <xsl:variable name="child-decls" select="$root-decl/xs:complexType/xs:sequence/xs:element"/>
    <xsl:variable name="decls-after" select="$child-decls[preceding-sibling::xs:element[@name eq 's']]"/>
    <xsl:sequence select="*[local-name() = $decls-after/@name]"/>
  </xsl:variable>

这显然更复杂,但现在您不必在代码中列出任何元素(s"除外).每当您更改架构时(特别是,如果您要添加新元素),脚本的行为将自动更新.这是否矫枉过正取决于您的项目.我只是将它作为一个可选的附加组件提供.:-)

This is obviously more complicated, but now you don't have to list any elements (other than "s") in your code. The script's behavior will automatically update whenever you change the schema (in particular, if you were to add new elements). Whether this is overkill or not depends on your project. I offer it simply as an optional add-on. :-)

这篇关于在现有文档的特定位置插入 XML 节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆