如何判断DOM操作中当前处理的是哪个同名manufacturedMaterial节点?
问题描述
我有一个包含两个<manufacturedMaterial>元素的XML文件,使用代码NodeList nodes = dom.getElementsByTagName("manufacturedMaterial");获取节点后,添加子元素时发现子元素会被同时加到第二个<manufacturedMaterial>节点中。当前使用的循环代码如下:
for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); }
请问有没有办法判断当前处理的是第一个还是第二个<manufacturedMaterial>节点?对应的XML结构如下:
<product> <manufacturedProduct classCode="MANU"> <templateId root="1.3.6.1.4.1.12559.11.10.1.3.1.3.1"/> <templateId root="2.16.840.1.113883.10.20.1.53"/> <manufacturedMaterial classCode="MMAT" determinerCode="KIND"> <code code="10219000" codeSystem="0.4.0.127.0.16.1.1.2.1" codeSystemName="EDQM" codeSystemVersion="2022-01-18" displayName="Tablet"/> <name>ALGOFEN TABLET 500MG</name> <epsos:desc xmlns="">500 mg</epsos:desc> <epsos:formCode xmlns="" code="658244" codeSystem="2.16.724.4.21.5.15.4" displayName="PARACETAMOL NORMON 500MG 20 COMPRIMIDOS EFG"/> <epsos:asContent xmlns="urn:epsos-org:ep:medication" classCode="CONT"> <epsos:containerPackagedMedicine xmlns="" classCode="CONT" determinerCode="INSTANCE"> <epsos:name/> <epsos:formCode code="116" codeSystem="1.3.6.1.4.1.12559.11.10.1.3.1.44.4" codeSystemName="eHDSIDisplayLabel" displayName=""/> <epsos:capacityQuantity unit="1" value="20.0"/> <epsos:capTypeCode nullFlavor="NA"/> </epsos:containerPackagedMedicine> </epsos:asContent> <epsos:asSpecializedKind xmlns="urn:epsos-org:ep:medication" classCode="GEN"> <epsos:generalizedMedicineClass classCode="MMAT"> <code code="N02BE01" codeSystem="2.16.840.1.113883.6.73" codeSystemName="Anatomical Therapeutic Chemical" codeSystemVersion="2022-01" displayName="paracetamol"/> </epsos:generalizedMedicineClass> </epsos:asSpecializedKind> </manufacturedMaterial> </manufacturedProduct> </product> <entryRelationship typeCode="REFR"> <sequenceNumber value="1"/> <substanceAdministration classCode="SBADM" moodCode="INT"> <id extension="JE000233461" root="2.16.724.4.9.30.40"/> <text> <reference value="#medicine.1"/> </text> <statusCode code="completed"/> <effectiveTime nullFlavor="UNK" xsi:type="IVL_TS"/> <doseQuantity nullFlavor="UNK"/> <consumable typeCode="CSM"> <manufacturedProduct classCode="MANU"> <templateId root="1.3.6.1.4.1.12559.11.10.1.3.1.3.1"/> <templateId root="2.16.840.1.113883.10.20.1.53"/> <manufacturedMaterial classCode="MMAT" determinerCode="KIND"> <code code="10219000" codeSystem="0.4.0.127.0.16.1.1.2.1" codeSystemName="EDQM" codeSystemVersion="2022-01-18" displayName="Tablet"/> <name>PARACETAMOL NORMON 500 mg COMPRIMIDOS EFGPARACETAMOL NORMON 500 mg COMPRIMIDOS EFG</name> <epsos:formCode xmlns=""/> <epsos:asContent xmlns="urn:epsos-org:ep:medication" classCode="CONT"> <epsos:containerPackagedMedicine xmlns="" classCode="CONT" determinerCode="INSTANCE"> <epsos:name/> <epsos:formCode/> <epsos:capacityQuantity/> <epsos:capTypeCode nullFlavor="NA"/> </epsos:containerPackagedMedicine> </epsos:asContent> <epsos:asSpecializedKind xmlns="urn:epsos-org:ep:medication" classCode="GEN"> <epsos:generalizedMedicineClass classCode="MMAT"> <code code="N02BE01" codeSystem="2.16.840.1.113883.6.73" codeSystemName="Anatomical Therapeutic Chemical" codeSystemVersion="2022-01" displayName="paracetamol"/> </epsos:generalizedMedicineClass> </epsos:asSpecializedKind> </manufacturedMaterial> </manufacturedProduct> </consumable> </substanceAdministration> </entryRelationship>
解决方案
方法1:利用循环索引直接判断
循环变量i本身就是节点的序号(从0开始),直接通过i的值就能区分第一个和第二个节点:
for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (i == 0) { // 处理第一个manufacturedMaterial节点 // 示例:添加子元素 Element newElem = dom.createElement("newElement"); newElem.setTextContent("firstNodeContent"); node.appendChild(newElem); } else if (i == 1) { // 处理第二个manufacturedMaterial节点 Element newElem = dom.createElement("newElement"); newElem.setTextContent("secondNodeContent"); node.appendChild(newElem); } }
方法2:通过节点上下文(父节点)区分
如果后续节点数量可能变化,可以通过节点的父级结构判断:
- 第一个
<manufacturedMaterial>的上层路径是<product>→<manufacturedProduct> - 第二个的上层路径是
<entryRelationship>→<substanceAdministration>→<consumable>→<manufacturedProduct>
代码示例:
for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); // 追溯到上层差异节点 Node parent = node.getParentNode(); Node grandParent = parent.getParentNode(); if ("product".equals(grandParent.getNodeName())) { // 第一个节点 } else if ("consumable".equals(grandParent.getNodeName())) { // 第二个节点 } }
方法3:通过节点内容差异区分
两个<manufacturedMaterial>的<name>子元素内容不同,也可以读取该值判断:
for (int i = 0; i < nodes.getLength(); i++) { Element material = (Element) nodes.item(i); Node nameNode = material.getElementsByTagName("name").item(0); String nameContent = nameNode.getTextContent(); if (nameContent.contains("ALGOFEN")) { // 第一个节点 } else if (nameContent.contains("PARACETAMOL NORMON")) { // 第二个节点 } }
关于子元素被重复添加的问题
你遇到的子元素同时出现在第二个节点的情况,大概率是因为重复使用了同一个Node对象。DOM规范中,一个节点只能属于一个父节点,当你把同一个子元素添加到新节点时,它会自动从原父节点移除。解决方法是:
- 为每个目标节点重新创建子元素对象
- 或者使用
cloneNode(true)复制子元素后再添加,示例:
Element templateElem = dom.createElement("newElement"); templateElem.setTextContent("content"); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); // 复制子元素,true表示复制所有子节点 Element clonedElem = (Element) templateElem.cloneNode(true); node.appendChild(clonedElem); }
内容的提问来源于stack exchange,提问作者zinon
相关产品推荐
相关产品推荐

