0

我正在尝试将几块 XML 代码从一个文件添加到另一个文件中。问题是,其中一些块具有不需要复制到目标 XML 文件中的根标记(如果根标记等于预定义的父标记,就是这种情况)。这是我目前用来插入片段的代码(用 Groovy 编写):

if (addCode.nodeName == parentTags) { //meaning the root tags shouldn't be included
    for (org.w3c.dom.Node n : addCode.childNodes) {
        //parent is a NodeList
        parent.item(parent.length - 1).appendChild(document.importNode(n, true))
    }
} else {
    parent.item(parent.length - 1).appendChild(document.importNode(addCode, true))
}

并解析 XML:

Document parseWithoutDTD(Reader r, boolean validating = false, boolean namespaceAware = true) {
    FactorySupport.createDocumentBuilderFactory().with { f ->
        f.namespaceAware = namespaceAware
        f.validating = validating
        f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        f.newDocumentBuilder().with { db ->
            db.parse(new InputSource(r))
        }
    }
}

这是一个不应包含根标签的示例 XML 文件:

<catalogue> <!-- shouldn't be included -->
    <message key='type_issuedate'>Date Issued</message>
    <message key='type_accessioneddate'>Date Accesioned</message>
</catalogue>

您可能已经注意到了这个问题:如果我将 XML 文件中的根标记省略以复制到另一个 XML 文件中,它们会引发解析异常。

编辑:这是要插入的文件的(缩短的)示例:

<catalogue xml:lang="en" xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
    ...
    <message key="column4">Date</message>
    <message key="column5">Summary</message>
    <message key="column6">Actions</message>
    <message key="restore">Restore</message>
    <message key="update">Update</message>
    <!-- INSERT XML HERE -->
    ...
</catalogue>

还有一个包含根标签的 XML 示例(以及要插入的相应文件):

要插入的 XML

<dependency>
    <groupId>grID</groupId>
    <artifactId>artID</artifactId>
    <version>${version.number}</version>
</dependency>

要插入的 XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<project>
  <dependencies>
    <dependency>
        <groupId>grID1</groupId>
        <artifactId>artID1</artifactId>
        <type>jar</type>
        <classifier>classes</classifier>
    </dependency>
    <!-- INSERT XML HERE -->
  </dependencies>
</project>

目前,所有这些代码都没有像我希望的那样工作。有人可以帮我吗?

非常感激!

4

1 回答 1

0

我认为(如果我理解正确的话),你需要这样的东西:

def insert( parent, data ) {
  if( parent.name() == data.name() ) {
    data.children().each {
      parent.append it
    }
  }
  else {
    parent.append data
  }
}

所以,给定

def newdoc = '''<dependency>
               |    <groupId>grID</groupId>
               |    <artifactId>artID</artifactId>
               |    <version>${version.number}</version>
               |</dependency>'''.stripMargin()

def doc = '''<?xml version="1.0" encoding="UTF-8"?>
            |<project>
            |  <dependencies>
            |    <dependency>
            |        <groupId>grID1</groupId>
            |        <artifactId>artID1</artifactId>
            |        <type>jar</type>
            |        <classifier>classes</classifier>
            |    </dependency>
            |  </dependencies>
            |</project>'''.stripMargin()

def docnode = new XmlParser().parseText( doc )
def newnode = new XmlParser().parseText( newdoc )

// use head() as I want to add to the first dependencies node
insert( docnode.dependencies.head(), newnode )
println groovy.xml.XmlUtil.serialize( docnode )

你得到输出:

<?xml version="1.0" encoding="UTF-8"?><project>
  <dependencies>
    <dependency>
      <groupId>grID1</groupId>
      <artifactId>artID1</artifactId>
      <type>jar</type>
      <classifier>classes</classifier>
    </dependency>
    <dependency>
      <groupId>grID</groupId>
      <artifactId>artID</artifactId>
      <version>${version.number}</version>
    </dependency>
  </dependencies>
</project>

并给出:

def newdoc = '''<catalogue>
               |    <message key='type_issuedate'>Date Issued</message>
               |    <message key='type_accessioneddate'>Date Accesioned</message>
               |</catalogue>'''.stripMargin()

def doc = '''<catalogue xml:lang="en" xmlns:i18n="http://apache.org/cocoon/i18n/2.1">
            |    <message key="column4">Date</message>
            |    <message key="column5">Summary</message>
            |    <message key="column6">Actions</message>
            |    <message key="restore">Restore</message>
            |    <message key="update">Update</message>
            |</catalogue>'''.stripMargin()

def docnode = new XmlParser().parseText( doc )
def newnode = new XmlParser().parseText( newdoc )

insert( docnode, newnode )
println groovy.xml.XmlUtil.serialize( docnode )

你得到:

<?xml version="1.0" encoding="UTF-8"?><catalogue xml:lang="en" xmlns:xml="http://www.w3.org/XML/1998/namespace">
  <message key="column4">Date</message>
  <message key="column5">Summary</message>
  <message key="column6">Actions</message>
  <message key="restore">Restore</message>
  <message key="update">Update</message>
  <message key="type_issuedate">Date Issued</message>
  <message key="type_accessioneddate">Date Accesioned</message>
</catalogue>

编辑

好的,鉴于额外的信息,这有帮助吗?给定与上面相同的newdoc字符串doc,该脚本似乎可以执行您想要的操作...

import groovy.xml.*
import groovy.xml.dom.*
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

Document parseWithoutDTD(Reader r, boolean validating = false, boolean namespaceAware = true) {
    FactorySupport.createDocumentBuilderFactory().with { f ->
        f.namespaceAware = namespaceAware
        f.validating = validating
        f.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
        f.newDocumentBuilder().with { db ->
            db.parse(new InputSource(r))
        }
    }
}

def addCode  = parseWithoutDTD( new StringReader( newdoc ) ).documentElement
def document = parseWithoutDTD( new StringReader( doc ) )
def parent   = document.documentElement
def parentTags = 'catalogue'

use( DOMCategory ) {
  if( addCode.nodeName == parentTags ) {
    addCode.childNodes.each { node ->
      parent.appendChild( document.importNode( node, true ) )
    }
  }
  else {
    parent.appendChild( document.importNode( addCode, true ) )
  }
}
于 2013-05-02T10:33:08.207 回答