根据 Java 中的值重新创建 XML

Posted

技术标签:

【中文标题】根据 Java 中的值重新创建 XML【英文标题】:Recreate an XML based on its values in Java 【发布时间】:2021-08-03 18:28:16 【问题描述】:

我有一个动态 XML,需要根据其 XML 的值进行转换。需要删除属性为type="newNode" 的组节点,因为它们已经派生了。

我尝试了以下方法:

    根据 XML 创建新节点并删除不必要的节点,但我在使用 doc.removeChild(node) 说时遇到了问题

    线程“主”org.w3c.dom.DOMException 中的异常:NOT_FOUND_ERR:尝试在不存在的上下文中引用节点。

    NodeList nodeList = doc.getElementsByTagName(NODE_MAPPINGS_NODE);
    for (int i = 0; i < nodeList.getLength(); i++) 
        Node nodeToBeRemoved = nodeList.item(i);
        if (nodeToBeRemoved.getNodeType() == Node.ELEMENT_NODE) 
            doc.getDocumentElement().removeChild(nodeToBeRemoved);
        
    
    

    基于原始文档创建了一个新文档,但我遇到了错误提示

    线程“main”org.w3c.dom.DOMException 中的异常:HIERARCHY_REQUEST_ERR:试图在不允许的地方插入节点。

    NodeList nodeList = doc.getElementsByTagName(NODE_MAPPINGS_NODE);
    for (int i = 0; i < nodeList.getLength(); i++) 
        Node node = nodeList.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) 
            if(!node.hasAttributes()) 
                Element elem = newDoc.createElement(node.getNodeName());
                newDoc.appendChild(elem);
            
        
    
    

这是我尝试解析的示例 XML:

<root>
    <input>
        <nodeMappings type="newNode">
            <name>declarationType</name>
            <type>derived</type>
            <derivedValue>X</derivedValue>
        </nodeMappings>
        <nodeMappings type="newNode">
            <name>identificationNumber</name>
            <type>derived</type>
            <derivedValue>5000000612</derivedValue>
        </nodeMappings>
        <characteristicsOfTaxPayer>
            <nodeMappings type="newNode">
                <name>collectivePerson</name>
                <type>derived</type>
                <derivedValue>X</derivedValue>
            </nodeMappings>
        </characteristicsOfTaxPayer>
        <listTest>
            <nodeMappings type="newNode">
                <name>primaryKey</name>
                <type>derived</type>
                <derivedValue>1</derivedValue>
            </nodeMappings>
            <nodeMappings type="newNode">
                <name>value</name>
                <type>derived</type>
                <derivedValue>test1</derivedValue>
            </nodeMappings>
        </listTest>
        <listTest>
            <nodeMappings type="newNode">
                <name>primaryKey</name>
                <type>derived</type>
                <derivedValue>2</derivedValue>
            </nodeMappings>
            <nodeMappings type="newNode">
                <name>value</name>
                <type>derived</type>
                <derivedValue>test2</derivedValue>
            </nodeMappings>
        </listTest>
    </input>
</root>

处理后应该是这样的:

<root>
    <input>
        <declarationType>X</declarationType>
        <identificationNumber>5000000612</identificationNumber>
        <characteristicsOfTaxPayer>
            <collectivePerson>X</collectivePerson>
        </characteristicsOfTaxPayer>
        <listTest>
            <primaryKey>1</primaryKey>
            <primaryKey>test1</primaryKey>
        </listTest>
        <listTest>
            <primaryKey>2</primaryKey>
            <primaryKey>test2</primaryKey>
        </listTest>
    </input>
</root>

有没有更好的方法来做到这一点?

【问题讨论】:

好像有一处不一致,或者我弄错了。但是除了 value 之外,所有新元素都是基于名称元素创建的。这成为primaryKey。对吗? 【参考方案1】:

整个工作可以用一个简单的 xslt 来完成。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  
  <xsl:output method="xml" encoding="utf-8" indent="yes"/>
  
  <!-- Identity template : copy all text nodes, elements and attributes -->   
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="nodeMappings[@type='newNode']" >
    <xsl:element name="name/text()"><xsl:value-of select="derivedValue/text()"/></xsl:element>
  </xsl:template>

</xsl:stylesheet>

如果约定中有一个例外是正确的:文本值名称元素成为新创建的元素,即&lt;name&gt;value&lt;/name&gt; 成为&lt;primaryKey/&gt;,xslt 将是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  
  <xsl:output method="xml" encoding="utf-8" indent="yes"/>
  
  <!-- Identity template : copy all text nodes, elements and attributes -->   
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="nodeMappings[@type='newNode']" >
    <xsl:element name="name/text()"><xsl:value-of select="derivedValue/text()"/></xsl:element>
  </xsl:template>

  <xsl:template match="nodeMappings[@type='newNode'][name='value']" >
    <primaryKey><xsl:value-of select="derivedValue/text()"/></primaryKey>
  </xsl:template>

</xsl:stylesheet>

【讨论】:

这是否回答了您的问题? 我目前正在尝试研究 XSLT,因为我以前从未尝试过它,而且我不确定我是否可以在我的代码中实现它,因为我们使用的是我们公司创建的框架。 如果你选择使用xsl(如果你想转换xml没有更好的语言),我建议你看看saxon-he。对于 Java 中的实现,请参见 ***.com/questions/40181386/…

以上是关于根据 Java 中的值重新创建 XML的主要内容,如果未能解决你的问题,请参考以下文章

麻烦请问一下,android如何修改xml文件中节点的值,并保存进去,谢谢

无法根据 UIPickerview 中第一个组件中的值重新加载第二个组件

将一个整型数组中的值逆序重新存放。用java编写

重新排列和排序

如何根据列的值对观察值重新编号[重复]

Java8系列重新认识HashMap