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

查看:145
本文介绍了在现有文档的特定位置插入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>

应在节点<r><t>之间插入新节点(<s>...</s>),结果:

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?

thx,MyKey _

thx, MyKey_

推荐答案

[替换了我的最后一个答案.现在,我对您的需求有了更好的了解.]

[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天全站免登陆