且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在现有文档的特定位置插入XML节点

更新时间:2022-12-28 12:47:33

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

[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. :-)