/*
 *      Copyright (c) 2018-2028, DreamLu All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: DreamLu 卢春梦 (596392912@qq.com)
 */
package com.docus.server.archive.utils;

import com.docus.core.util.Exceptions;
import com.docus.core.util.IoUtil;
import org.springframework.lang.Nullable;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

/**
 * xpath解析xml
 *
 * <pre>
 *     文档地址：
 *     http://www.w3school.com.cn/xpath/index.asp
 * </pre>
 *
 * @author L.cm
 */
public class XmlUtil {
	private final XPath path;
	private final Document doc;

	private XmlUtil(InputSource inputSource) throws ParserConfigurationException, SAXException, IOException {
		DocumentBuilderFactory dbf = getDocumentBuilderFactory();
		DocumentBuilder db = dbf.newDocumentBuilder();
		doc = db.parse(inputSource);
		path = getXPathFactory().newXPath();
	}

	/**
	 * 创建工具类
	 *
	 * @param inputSource inputSource
	 * @return XmlUtil
	 */
	private static XmlUtil create(InputSource inputSource) {
		try {
			return new XmlUtil(inputSource);
		} catch (ParserConfigurationException | SAXException | IOException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 转换工具类
	 *
	 * @param inputStream inputStream
	 * @return XmlUtil
	 */
	public static XmlUtil of(InputStream inputStream) {
		InputSource inputSource = new InputSource(inputStream);
		return create(inputSource);
	}

	/**
	 * 转换工具类
	 *
	 * @param xmlStr xmlStr
	 * @return XmlUtil
	 */
	public static XmlUtil of(String xmlStr) {
		StringReader sr = new StringReader(xmlStr.trim());
		InputSource inputSource = new InputSource(sr);
		XmlUtil xmlUtil = create(inputSource);
		IoUtil.closeQuietly(sr);
		return xmlUtil;
	}

	/**
	 * 转换路径
	 *
	 * @param expression 表达式
	 * @param item       实体
	 * @param returnType 返回类型
	 * @return Object
	 */
	private Object evalXPath(String expression, @Nullable Object item, QName returnType) {
		item = null == item ? doc : item;
		try {
			return path.evaluate(expression, item, returnType);
		} catch (XPathExpressionException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 获取String
	 *
	 * @param expression 路径
	 * @return {String}
	 */
	public String getString(String expression) {
		return (String) evalXPath(expression, null, XPathConstants.STRING);
	}

	/**
	 * 获取Boolean
	 *
	 * @param expression 路径
	 * @return {String}
	 */
	public Boolean getBoolean(String expression) {
		return (Boolean) evalXPath(expression, null, XPathConstants.BOOLEAN);
	}

	/**
	 * 获取Number
	 *
	 * @param expression 路径
	 * @return {Number}
	 */
	public Number getNumber(String expression) {
		return (Number) evalXPath(expression, null, XPathConstants.NUMBER);
	}

	/**
	 * 获取某个节点
	 *
	 * @param expression 路径
	 * @return {Node}
	 */
	public Node getNode(String expression) {
		return (Node) evalXPath(expression, null, XPathConstants.NODE);
	}

	/**
	 * 获取子节点
	 *
	 * @param expression 路径
	 * @return NodeList
	 */
	public NodeList getNodeList(String expression) {
		return (NodeList) evalXPath(expression, null, XPathConstants.NODESET);
	}


	/**
	 * 获取String
	 *
	 * @param node       节点
	 * @param expression 相对于node的路径
	 * @return {String}
	 */
	public String getString(Object node, String expression) {
		return (String) evalXPath(expression, node, XPathConstants.STRING);
	}

	/**
	 * 获取
	 *
	 * @param node       节点
	 * @param expression 相对于node的路径
	 * @return {String}
	 */
	public Boolean getBoolean(Object node, String expression) {
		return (Boolean) evalXPath(expression, node, XPathConstants.BOOLEAN);
	}

	/**
	 * 获取
	 *
	 * @param node       节点
	 * @param expression 相对于node的路径
	 * @return {Number}
	 */
	public Number getNumber(Object node, String expression) {
		return (Number) evalXPath(expression, node, XPathConstants.NUMBER);
	}

	/**
	 * 获取某个节点
	 *
	 * @param node       节点
	 * @param expression 路径
	 * @return {Node}
	 */
	public Node getNode(Object node, String expression) {
		return (Node) evalXPath(expression, node, XPathConstants.NODE);
	}

	/**
	 * 获取子节点
	 *
	 * @param node       节点
	 * @param expression 相对于node的路径
	 * @return NodeList
	 */
	public NodeList getNodeList(Object node, String expression) {
		return (NodeList) evalXPath(expression, node, XPathConstants.NODESET);
	}

	/**
	 * 针对没有嵌套节点的简单处理
	 *
	 * @return map集合
	 */
	public Map<String, String> toMap() {
		Element root = doc.getDocumentElement();
		Map<String, String> params = new HashMap<>(16);

		// 将节点封装成map形式
		NodeList list = root.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);
			if (node instanceof Element) {
				params.put(node.getNodeName(), node.getTextContent());
			}
		}
		return params;
	}

	private static volatile boolean preventedXXE = false;

	private static DocumentBuilderFactory getDocumentBuilderFactory() throws ParserConfigurationException {
		DocumentBuilderFactory dbf = XmlHelperHolder.documentBuilderFactory;
		if (!preventedXXE) {
			synchronized (XmlUtil.class) {
				if (!preventedXXE) {
					preventXXE(dbf);
				}
			}
		}
		return dbf;
	}

	/**
	 * preventXXE
	 *
	 * @param dbf
	 * @throws ParserConfigurationException
	 */
	private static void preventXXE(DocumentBuilderFactory dbf) throws ParserConfigurationException {
		// This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
		// Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
		dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

		// If you can't completely disable DTDs, then at least do the following:
		// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
		// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities

		// JDK7+ - http://xml.org/sax/features/external-general-entities
		dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);

		// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
		// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities

		// JDK7+ - http://xml.org/sax/features/external-parameter-entities
		dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

		// Disable external DTDs as well
		dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

		// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
		dbf.setXIncludeAware(false);
		dbf.setExpandEntityReferences(false);
		preventedXXE = true;
	}

	private static XPathFactory getXPathFactory() {
		return XmlHelperHolder.xPathFactory;
	}

	/**
	 * 内部类单例
	 */
	private static class XmlHelperHolder {
		private static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		private static XPathFactory xPathFactory = XPathFactory.newInstance();
	}
	private static String str;
	static {
		str="<PRPA_HIP0032 xmlns=\"urn:hl7-org:v3\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ITSVersion=\"XML_1.0\" xsi:schemaLocation=\"urn:hl7-org:v3\">  \n" +
				"  <!--id-消息流水号-->  \n" +
				"  <id extension=\"0f7e4a58-7ce3-436d-8d1b-aee3734e390b\"/>  \n" +
				"  <!--creationTime-消息创建时间-->  \n" +
				"  <creationTime value=\"20230217112826\"/>  \n" +
				"  <!--interactionId-消息的服务标识-->  \n" +
				"  <interactionId root=\"2.16.840.1.113883.1.6\" extension=\"PRPA_IN400003UV\"/>  \n" +
				"  <!--processingCode-处理代码。标识此消息是否是产品、训练、调试系统的一部分。D：调试；P：产\n" +
				"品；T：训练-->  \n" +
				"  <processingCode code=\"P\"/>  \n" +
				"  <!--\n" +
				"processingModeCode-处理模型代码。定义此消息是一个文档处理还是一个初始装载的一部分。A：\n" +
				"存档；I：初始装载；R：从存档中恢复；T：当前处理，间隔传递。\n" +
				"-->  \n" +
				"  <processingModeCode/>  \n" +
				"  <!--\n" +
				"acceptAckCode-接收确认类型 AL：总是确认；NE：从不确认；ER：仅在错误/或拒绝时确认；SU： 仅在成功完成时确认。\n" +
				"-->  \n" +
				"  <acceptAckCode code=\"AL\"/>  \n" +
				"  <receiver typeCode=\"RCV\"> \n" +
				"    <device classCode=\"DEV\" determinerCode=\"INSTANCE\"> \n" +
				"      <id> \n" +
				"        <item extension=\"Orion-001\"/> \n" +
				"      </id> \n" +
				"    </device> \n" +
				"  </receiver>  \n" +
				"  <sender typeCode=\"SND\"> \n" +
				"    <device classCode=\"DEV\" determinerCode=\"INSTANCE\"> \n" +
				"      <id> \n" +
				"        <item extension=\"InpatienTransfer-001\"/> \n" +
				"      </id> \n" +
				"    </device> \n" +
				"  </sender>  \n" +
				"  <controlActProcess classCode=\"INFO\" moodCode=\"PRP\"> \n" +
				"    <code code=\"DischargeInfoAdd\"> \n" +
				"      <displayName value=\"出院登记信息新增\"/> \n" +
				"    </code>  \n" +
				"    <subject typeCode=\"SUBJ\"> \n" +
				"      <encounterEvent classCode=\"ENC\" moodCode=\"EVN\"> \n" +
				"        <id> \n" +
				"          <!--住院号标识 -->  \n" +
				"          <item root=\"2.16.156.10011.1.12\" extension=\"10082654\"/> \n" +
				"        </id>  \n" +
				"        <!--住院流水号-->  \n" +
				"        <item root=\"1.2.156.10011.1.2.1.6\" extension=\"213080\"/>  \n" +
				"        <!--就诊事件类别代码-->  \n" +
				"        <code code=\"3\" codeSystem=\"2.16.156.10011.2.3.1.271\" codeSystemName=\"患者类型代码表\"> \n" +
				"          <displayName value=\"住院\"/> \n" +
				"        </code>  \n" +
				"        <statusCode/>  \n" +
				"        <!--入\\出院日期时间-->  \n" +
				"        <effectiveTime> \n" +
				"          <low value=\"20230214100923\"/>  \n" +
				"          <high value=\"20230217160046\"/> \n" +
				"        </effectiveTime>  \n" +
				"        <!--住院天数-->  \n" +
				"        <lengthOfStayQuantity unit=\"天\" value=\"3\"/>  \n" +
				"        <!--住院次数-->  \n" +
				"        <lengthOfStayQuantity unit=\"次\" value=\"1\"/>  \n" +
				"        <!--患者-->  \n" +
				"        <subject typeCode=\"SBJ\"> \n" +
				"          <patient classCode=\"PAT\"> \n" +
				"            <!-- 域ID -->  \n" +
				"            <id root=\"1.2.156.112635.1.2.1.2\" extension=\"03\"/>  \n" +
				"            <id> \n" +
				"              <!--PatientID-->  \n" +
				"              <item extension=\"z002082795000\"/> \n" +
				"            </id>  \n" +
				"            <!--患者基本信息-->  \n" +
				"            <patientPerson> \n" +
				"              <!--患者身份证号-->  \n" +
				"              <id> \n" +
				"                <item root=\"2.16.156.10011.1.3\" extension=\"450881200609066029\"/> \n" +
				"              </id>  \n" +
				"              <administrativeGenderCode code=\"2\" codeSystem=\"1.2.156.112635.1.1.3\" codeSystemName=\"生理性别代码表（GB/T 2261.1）\" displayName=\"女性\"/>  \n" +
				"              <!--年龄（岁）/（月）-->  \n" +
				"              <age unit=\"岁\" value=\"16岁\"/>  \n" +
				"              <!--姓名-->  \n" +
				"              <name xsi:type=\"DSET_EN\"> \n" +
				"                <item> \n" +
				"                  <part value=\"谢雨欣\"/> \n" +
				"                </item> \n" +
				"              </name> \n" +
				"            </patientPerson> \n" +
				"          </patient> \n" +
				"        </subject>  \n" +
				"        <!--登记人-->  \n" +
				"        <discharger typeCode=\"DIS\"> \n" +
				"          <time>20230217112653</time>  \n" +
				"          <assignedPerson classCode=\"ASSIGNED\"> \n" +
				"            <!--登记人职工号-->  \n" +
				"            <id> \n" +
				"              <item root=\"2.16.156.10011.1.4\" extension=\"A-166\"/> \n" +
				"            </id>  \n" +
				"            <assignedPerson classCode=\"PSN\" determinerCode=\"INSTANCE\"> \n" +
				"              <!--登记人姓名 -->  \n" +
				"              <name xsi:type=\"DSET_EN\"> \n" +
				"                <item> \n" +
				"                  <part value=\"潘丽华\"/> \n" +
				"                </item> \n" +
				"              </name> \n" +
				"            </assignedPerson> \n" +
				"          </assignedPerson> \n" +
				"        </discharger>  \n" +
				"        <!-- 主任医师签名 -->  \n" +
				"        <authenticator displayName=\"主任医师\"> \n" +
				"          <!--记录时间-->  \n" +
				"          <time value=\"\"/>  \n" +
				"          <signatureCode/>  \n" +
				"          <assignedEntity> \n" +
				"            <id root=\"1.2.156.112635.1.1.2\" extension=\"1-173\"/>  \n" +
				"            <code displayName=\"主任医师\"/>  \n" +
				"            <assignedPerson classCode=\"PSN\" determinerCode=\"INSTANCE\"> \n" +
				"              <name>陈勇明</name> \n" +
				"            </assignedPerson> \n" +
				"          </assignedEntity> \n" +
				"        </authenticator>  \n" +
				"        <!-- 主治医师签名 -->  \n" +
				"        <authenticator displayName=\"主治医师\"> \n" +
				"          <time value=\"\"/>  \n" +
				"          <signatureCode/>  \n" +
				"          <assignedEntity> \n" +
				"            <id root=\"1.2.156.112635.1.1.2\" extension=\"1-691\"/>  \n" +
				"            <code displayName=\"主治医师\"/>  \n" +
				"            <assignedPerson classCode=\"PSN\" determinerCode=\"INSTANCE\"> \n" +
				"              <name>张存良</name> \n" +
				"            </assignedPerson> \n" +
				"          </assignedEntity> \n" +
				"        </authenticator>  \n" +
				"        <!-- 住院医师签名 -->  \n" +
				"        <authenticator displayName=\"住院医师\"> \n" +
				"          <time value=\"\"/>  \n" +
				"          <signatureCode/>  \n" +
				"          <assignedEntity> \n" +
				"            <id root=\"1.2.156.112635.1.1.2\" extension=\"1-691\"/>  \n" +
				"            <code displayName=\"住院医师\"/>  \n" +
				"            <assignedPerson classCode=\"PSN\" determinerCode=\"INSTANCE\"> \n" +
				"              <name>张存良</name> \n" +
				"            </assignedPerson> \n" +
				"          </assignedEntity> \n" +
				"        </authenticator>  \n" +
				"        <!-- 出院病床号、病房、病区、科室和医院的关联 -->  \n" +
				"        <componentOf> \n" +
				"          <encompassingEncounter> \n" +
				"            <effectiveTime/>  \n" +
				"            <location> \n" +
				"              <healthCareFacility> \n" +
				"                <serviceProviderOrganization> \n" +
				"                  <asOrganizationPartOf classCode=\"PART\"> \n" +
				"                    <!-- DE01.00.026.00 病床号 -->  \n" +
				"                    <wholeOrganization classCode=\"ORG\" determinerCode=\"INSTANCE\"> \n" +
				"                      <id root=\"1.2.156.112635.1.2.1.8\" extension=\"59\"/>  \n" +
				"                      <name>59</name>  \n" +
				"                      <!-- DE01.00.019.00 病房号 -->  \n" +
				"                      <asOrganizationPartOf classCode=\"PART\"> \n" +
				"                        <wholeOrganization classCode=\"ORG\" determinerCode=\"INSTANCE\"> \n" +
				"                          <id root=\"1.2.156.112635.1.2.1.28\" extension=\"001\"/>  \n" +
				"                          <name>205室</name>  \n" +
				"                          <!-- DE08.10.026.00 科室名称 -->  \n" +
				"                          <asOrganizationPartOf classCode=\"PART\"> \n" +
				"                            <wholeOrganization classCode=\"ORG\" determinerCode=\"INSTANCE\"> \n" +
				"                              <id root=\"1.2.156.112635.1.1.1\" extension=\"11\"/>  \n" +
				"                              <name>耳鼻咽喉头颈外科</name>  \n" +
				"                              <!-- DE08.10.054.00 病区名称 -->  \n" +
				"                              <asOrganizationPartOf classCode=\"PART\"> \n" +
				"                                <wholeOrganization classCode=\"ORG\" determinerCode=\"INSTANCE\"> \n" +
				"                                  <id root=\"1.2.156.112635.1.1.33\" extension=\"B021601\"/>  \n" +
				"                                  <name>2号楼16楼西区</name>  \n" +
				"                                  <!--XXX医院 -->  \n" +
				"                                  <asOrganizationPartOf classCode=\"PART\"> \n" +
				"                                    <wholeOrganization classCode=\"ORG\" determinerCode=\"INSTANCE\"> \n" +
				"                                      <id root=\"1.2.156.112635\" extension=\"4560886379\"/>  \n" +
				"                                      <name>南方医科大学顺德医院</name> \n" +
				"                                    </wholeOrganization> \n" +
				"                                  </asOrganizationPartOf> \n" +
				"                                </wholeOrganization> \n" +
				"                              </asOrganizationPartOf> \n" +
				"                            </wholeOrganization> \n" +
				"                          </asOrganizationPartOf> \n" +
				"                        </wholeOrganization> \n" +
				"                      </asOrganizationPartOf> \n" +
				"                    </wholeOrganization> \n" +
				"                  </asOrganizationPartOf> \n" +
				"                </serviceProviderOrganization> \n" +
				"              </healthCareFacility> \n" +
				"            </location> \n" +
				"          </encompassingEncounter> \n" +
				"        </componentOf>  \n" +
				"        <!-- 入院诊断章节 -->  \n" +
				"        <component displayName=\"入院诊断\"> \n" +
				"          <section> \n" +
				"            <code code=\"11450-4\" displayName=\"PROBLEM LIST\" codeSystem=\"2.16.840.1.113883.6.1\" codeSystemName=\"LOINC\"/>  \n" +
				"            <text/>  \n" +
				"            <!--入院诊断-西医条目-->  \n" +
				"            <entry displayName=\"入院诊断-西医条目\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE05.01.025.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断-西医诊断名称\"/>  \n" +
				"                <!--入院诊断日期-->  \n" +
				"                <effectiveTime value=\"20230214100923\"/>  \n" +
				"                <value xsi:type=\"ST\">突发特发性听觉丧失</value>  \n" +
				"                <entryRelationship typeCode=\"COMP\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--入院诊断-西医诊断编码-代码-->  \n" +
				"                    <code code=\"DE05.01.024.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断-西医诊断编码\"/>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.11\" codeSystemName=\"ICD-10\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <!--入院诊断-中医条目-->  \n" +
				"            <entry displayName=\"入院诊断-中医条目\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE05.10.172.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断-中医病名名称\"/>  \n" +
				"                <!--入院诊断日期-->  \n" +
				"                <effectiveTime value=\"20230214100923\"/>  \n" +
				"                <value xsi:type=\"ST\">无</value>  \n" +
				"                <entryRelationship typeCode=\"COMP\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--入院诊断-中医诊断编码-代码-->  \n" +
				"                    <code code=\"\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断-中医病名代码\"/>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.14\" codeSystemName=\"中医病证分类与代码表( GB/T 15657)\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship typeCode=\"COMP\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--入院诊断-中医证候编码-名称-->  \n" +
				"                    <code code=\"\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断-中医证候名称\"/>  \n" +
				"                    <value xsi:type=\"ST\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship typeCode=\"COMP\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--入院诊断-中医证候编码-代码-->  \n" +
				"                    <code code=\"DE05.10.130.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断-中医证候代码\"/>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.14\" codeSystemName=\"中医病证分类与代码表( GB/T 15657)\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <!--入院诊断顺位-->  \n" +
				"                <entryRelationship typeCode=\"COMP\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE05.01.080.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院诊断顺位\"/>  \n" +
				"                    <value xsi:type=\"INT\" value=\"1\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"阳性辅助检查\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE04.50.128.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"阳性辅助检查结果\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"中医“四诊”观察\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE02.10.028.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"中医“四诊”观察结果\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"治则治法\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE06.00.300.00\" displayName=\"治则治法\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry> \n" +
				"          </section> \n" +
				"        </component>  \n" +
				"        <!-- 主要健康问题章节 -->  \n" +
				"        <component displayName=\"主要健康问题\"> \n" +
				"          <section> \n" +
				"            <code code=\"11450-4\" displayName=\"Problem list\" codeSystem=\"2.16.840.1.113883.6.1\" codeSystemName=\"LOINC\"/>  \n" +
				"            <text/>  \n" +
				"            <entry> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE05.10.148.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"入院情况\"/>  \n" +
				"                <value xsi:type=\"ST\">常规</value> \n" +
				"              </observation> \n" +
				"            </entry> \n" +
				"          </section> \n" +
				"        </component>  \n" +
				"        <!-- 住院过程章节 -->  \n" +
				"        <component displayName=\"住院过程\"> \n" +
				"          <section> \n" +
				"            <code code=\"8648-8\" displayName=\"Hospital Course\" codeSystem=\"2.16.840.1.113883.6.1\" codeSystemName=\"LOINC\"/>  \n" +
				"            <text/>  \n" +
				"            <entry> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE06.00.296.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"诊疗过程描述\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry> \n" +
				"          </section> \n" +
				"        </component>  \n" +
				"        <!-- 医嘱（用药）章节 -->  \n" +
				"        <component displayName=\"医嘱(用药)\"> \n" +
				"          <section> \n" +
				"            <code code=\"46209-3\" codeSystem=\"2.16.840.1.113883.6.1\" displayName=\"Provider Orders\" codeSystemName=\"LOINC\"/>  \n" +
				"            <text/>  \n" +
				"            <entry displayName=\"中药用药方法煎煮方法\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE08.50.047.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"中药用药方法煎煮方法\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"中药用药方法\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE06.00.136.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"中药用药方法\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry> \n" +
				"          </section> \n" +
				"        </component>  \n" +
				"        <!-- 出院诊断章节 -->  \n" +
				"        <component displayName=\"出院诊断\"> \n" +
				"          <section> \n" +
				"            <code code=\"11535-2\" displayName=\"Discharge Diagnosis\" codeSystem=\"2.16.840.1.113883.6.1\" codeSystemName=\"LOINC\"/>  \n" +
				"            <text/>  \n" +
				"            <entry displayName=\"出院情况\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE06.00.193.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院情况\"/>  \n" +
				"                <value xsi:type=\"ST\">治愈</value> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"出院日期时间\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE06.00.017.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院日期时间\"/>  \n" +
				"                <value xsi:type=\"TS\" value=\"20230217160046\"/> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <!--出院诊断-西医条目-->  \n" +
				"            <entry displayName=\"出院诊断-西医条目\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE05.01.025.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"西医诊断名称\"/>  \n" +
				"                <!--出院诊断日期-->  \n" +
				"                <effectiveTime value=\"20230217160046\"/>  \n" +
				"                <!-- 诊断医师信息 -->  \n" +
				"                <performer typeCode=\"PRF \"> \n" +
				"                  <assignedEntity> \n" +
				"                    <!-- 诊断医生编码 -->  \n" +
				"                    <id root=\"1.2.156.112635.1.1.2\" extension=\"1-691\"/>  \n" +
				"                    <assignedPerson determinerCode=\"INSTANCE\" classCode=\"PSN\"> \n" +
				"                      <!-- 诊断医生名称 -->  \n" +
				"                      <name>张存良</name> \n" +
				"                    </assignedPerson>  \n" +
				"                    <representedOrganization classCode=\"ORG\" determinerCode=\"INSTANCE\"> \n" +
				"                      <!-- 诊断科室编码 -->  \n" +
				"                      <id root=\"1.2.156.112635.1.1.1\" extension=\"11\"/>  \n" +
				"                      <!-- 诊断科室名称 -->  \n" +
				"                      <name>耳鼻咽喉头颈外科</name> \n" +
				"                    </representedOrganization> \n" +
				"                  </assignedEntity> \n" +
				"                </performer>  \n" +
				"                <!--诊断类别 -->  \n" +
				"                <code code=\"H91.200\" codeSystem=\"1.2.156.112635.1.1.29\"> \n" +
				"                  <displayName value=\"出院诊断\">突发特发性听觉丧失</displayName> \n" +
				"                </code>  \n" +
				"                <!-- 诊断依据 -->  \n" +
				"                <entryRelationship displayName=\"诊断依据\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE05.01.070.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录 \" displayName=\"诊断依据代码\"/>  \n" +
				"                    <value xsi:type=\"ST\" code=\"XXX\">文本</value> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship displayName=\"是否主要诊断\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code displayName=\"是否主要诊断\"/>  \n" +
				"                    <value xsi:type=\"BL\" value=\"false\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship displayName=\"是否待查\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code displayName=\"是否待查\"/>  \n" +
				"                    <value xsi:type=\"BL\" value=\"false\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship displayName=\"是否传染病\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code displayName=\"是否传染病\"/>  \n" +
				"                    <value xsi:type=\"BL\" value=\"false\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <!-- 诊断标识号 -->  \n" +
				"                <diagnosisNum value=\"诊断标识号\"/>  \n" +
				"                <value xsi:type=\"ST\"/>  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"出院诊断-西医诊断\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--出院诊断-西医诊断编码-代码-->  \n" +
				"                    <code code=\"DE05.01.024.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断-西医诊断编码\"/>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.11\" codeSystemName=\"ICD-10\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship displayName=\"其他西医诊断\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE05.01.024.00\" displayName=\"其他西医诊断编码\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\"> \n" +
				"                      <qualifier> \n" +
				"                        <name displayName=\"其他西医诊断编码\"/> \n" +
				"                      </qualifier> \n" +
				"                    </code>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.11\" codeSystemName=\"ICD-10\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <!--出院诊断顺位-->  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"出院诊断顺位\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE05.01.080.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断顺位\"/>  \n" +
				"                    <value xsi:type=\"INT\" value=\"01\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <!--其他医学处置-->  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"其他医学处置\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE06.00.251.00\" displayName=\"其他医学处置\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\"/>  \n" +
				"                    <value xsi:type=\"ST\">无</value> \n" +
				"                  </observation> \n" +
				"                </entryRelationship> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <!--出院诊断-中医条目-->  \n" +
				"            <entry displayName=\"出院诊断-中医条目\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE05.10.172.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断-中医病名代码\"/>  \n" +
				"                <!--出院诊断日期-->  \n" +
				"                <effectiveTime value=\"20230217160046\"/>  \n" +
				"                <!--中药使用类别-->  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"中药使用类别\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE06.00.164.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"中药使用类别代码\"/>  \n" +
				"                    <!--中药使用类别代码-->  \n" +
				"                    <value code=\"9\" displayName=\"其他中药\" codeSystem=\"2.16.156.10011.2.3.1.157\" codeSystemName=\"中药使用类别代码表\" xsi:type=\"CD\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <value xsi:type=\"ST\">乳房病类</value>  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"出院诊断-中医病名\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--出院诊断-中医诊断编码-代码-->  \n" +
				"                    <code code=\"DE05.10.130.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断-中医病名代码\"/>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.14\" codeSystemName=\"中医病证分类与代码表( GB/T 15657)\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"出院诊断-中医证候\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--出院诊断-中医证候编码-名称-->  \n" +
				"                    <code code=\"\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断-中医证候名称\"/>  \n" +
				"                    <value xsi:type=\"ST\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"出院诊断-中医证候\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <!--出院诊断-中医证候编码-代码-->  \n" +
				"                    <code code=\"DE05.10.130.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断-中医证候代码\"/>  \n" +
				"                    <value xsi:type=\"CD\" code=\"\" displayName=\"\" codeSystem=\"2.16.156.10011.2.3.3.14\" codeSystemName=\"中医病证分类与代码表( GB/T 15657)\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship>  \n" +
				"                <!--出院诊断顺位-->  \n" +
				"                <entryRelationship typeCode=\"COMP\" displayName=\"出院诊断顺位\"> \n" +
				"                  <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                    <code code=\"DE05.01.080.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院诊断顺位\"/>  \n" +
				"                    <value xsi:type=\"INT\" value=\"\"/> \n" +
				"                  </observation> \n" +
				"                </entryRelationship> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"出院时症状与体征\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE04.01.117.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院时症状与体征\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <entry displayName=\"出院医嘱\"> \n" +
				"              <observation classCode=\"OBS\" moodCode=\"EVN\"> \n" +
				"                <code code=\"DE06.00.287.00\" codeSystem=\"2.16.156.10011.2.2.1\" codeSystemName=\"卫生信息数据元目录\" displayName=\"出院医嘱\"/>  \n" +
				"                <value xsi:type=\"ST\"/> \n" +
				"              </observation> \n" +
				"            </entry>  \n" +
				"            <!-- 抗菌药物接口所需 -->  \n" +
				"            <antibacterial_drugs> \n" +
				"              <!-- 诊断类别 -->  \n" +
				"              <diagClass/>  \n" +
				"              <!-- 治疗情况 -->  \n" +
				"              <diagResult/>  \n" +
				"              <!-- 治愈医生工号 -->  \n" +
				"              <healDoc/> \n" +
				"            </antibacterial_drugs> \n" +
				"          </section> \n" +
				"        </component> \n" +
				"      </encounterEvent> \n" +
				"    </subject> \n" +
				"  </controlActProcess>  \n" +
				"  <emr> \n" +
				"    <!-- 离院方式 -->  \n" +
				"    <P_OUT_TYPE/>  \n" +
				"    <!-- 治疗转归 -->  \n" +
				"    <P_OUT_STATE>治愈</P_OUT_STATE>  \n" +
				"    <!-- 在院状态；在院是I，出院是O，取消入院是N -->  \n" +
				"    <P_IN_STATE>O</P_IN_STATE>  \n" +
				"    <!-- 总费用 -->  \n" +
				"    <TOTAL_COSTS>0</TOTAL_COSTS> \n" +
				"  </emr>  \n" +
				"  <!-- 抗菌药物接口所需 -->  \n" +
				"  <antibacterial_drugs> \n" +
				"    <!-- 出院结算类型代码 -->  \n" +
				"    <rcptPolicy>01</rcptPolicy>  \n" +
				"    <!-- 出院医嘱名称 -->  \n" +
				"    <dischgState>出院医嘱</dischgState> \n" +
				"  </antibacterial_drugs> \n" +
				"</PRPA_HIP0032>\n";
	}

	public static void main(String[] args) {
		XmlUtil  a=XmlUtil.of(str);
		Node node=null;
		//id-消息流水号
		node = a.getNode("/PRPA_HIP0032/id/@extension");
		String serialId  = node.toString();
		System.out.println(serialId);
		//住院流水号
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/item/@extension");
		String jzh = node.toString();
		System.out.println(jzh);
		//住院号标识
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/id/item/@extension");
		String inpatientNo = node.toString();
		System.out.println(inpatientNo);
		//住院次数[]
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/lengthOfStayQuantity[@unit='次']/@value");
		String admissTimes=node.toString();
		System.out.println(admissTimes);
		//姓名
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/subject/patient/patientPerson/name/item/part/@value");
		String name = node.toString();
		System.out.println(name);
		//入院日期时间
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/effectiveTime/low/@value");
		String admissDate = node.toString();
		System.out.println(admissDate);
		//出院日期时间
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/effectiveTime/high/@value");
		String disDate = node.toString();
		System.out.println(disDate);
		//入院诊断科室名称[]
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/component[@displayName='入院诊断']/section/entry[@displayName='入院诊断-西医条目']/observation/performer/assignedEntity/representedOrganization/name");
		String admissDeptName = node.getTextContent();
		System.out.println(admissDeptName);
		//出院诊断科室名称[]
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/component[@displayName='出院诊断']/section/entry[@displayName='出院诊断-西医条目']/observation/performer/assignedEntity/representedOrganization/name");
		String disDeptName = node.getTextContent();
		System.out.println(disDeptName);
		//主治医师[]
		node = a.getNode("/PRPA_HIP0032/controlActProcess/subject/encounterEvent/authenticator[@displayName='主治医师']/assignedEntity/assignedPerson/name");
		String attendingName = node.getTextContent();
		System.out.println(attendingName);
	}
}
