我有一个XML文件,其元素<Database>
有两个子元素<Patients> and <Hospitals>
。每个<Patients>
都有一个子元素<Patient>
,其名称指定为属性。每家医院都有一个属性名称,例如:<Hospital name="JR"
和子元素<Patients>
,其中包含子元素<Patient name="XY">
我想通过复制患者的结构来更新文件,但是要添加医院信息。作为患者姓名的附加属性,或作为子元素。有什么想法吗?
编辑:谢谢Tim,这是样本。<Database>
<Patients>
<Patient name="Salvatore"/>
<Patient name="Luca"/>
</Patients>
<Hospitals>
<Hospital name="JR">
<Patients>
<Patient name="Salvatore"/>
</Patients>
</Hospital>
<Hospital name="LondonGeneral">
<Patients>
<Patient name="Luca"/>
</Patients>
</Hospital>
</Hospitals>
</Database>
输出应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<Database>
<Patients>
<Patient name="Salvatore" hospital="JR"/>
<Patient name="Luca" hospital="LondonGeneral"/>
</Patients>
<Hospitals>
<Hospital name="JR">
<Patients>
<Patient name="Salvatore"/>
</Patients>
</Hospital>
<Hospital name="LondonGeneral">
<Patients>
<Patient name="Luca"/>
</Patients>
</Hospital>
</Hospitals>
</Database>
感谢您的帮助。
答案 0 :(得分:0)
假设每个患者姓名仅包含在一个Hospital
元素中,则以下内容应该起作用
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="hospitalPatientByName"
match="Hospital/Patients/Patient"
use="@name" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="Patient[not(ancestor::Hospital)]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:attribute name="hospital">
<xsl:value-of select="key('hospitalPatientByName', @name)/ancestor::Hospital/@name" />
</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我们通过患者姓名在Patient
元素下查找相应的Patient
来处理每个顶级Hospital
元素,然后提取包含医院的名称。
如果相同名称的Patient
可能不止一个Hospital
,那么我会使用子元素而不是属性
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="hospitalPatientByName"
match="Hospital/Patients/Patient"
use="@name" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="Patient[not(ancestor::Hospital)]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="key('hospitalPatientByName', @name)/ancestor::Hospital" mode="in-patient" />
</xsl:copy>
</xsl:template>
<xsl:template match="Hospital" mode="in-patient">
<xsl:copy><xsl:apply-templates select="@*" /></xsl:copy>
</xsl:template>
</xsl:stylesheet>
鉴于您的样本输入,这将产生
<Database>
<Patients>
<Patient name="Salvatore"><Hospital name="JR"/></Patient>
<Patient name="Luca"><Hospital name="LondonGeneral"/></Patient>
</Patients>
<Hospitals>
<Hospital name="JR">
<Patients>
<Patient name="Salvatore"/>
</Patients>
</Hospital>
<Hospital name="LondonGeneral">
<Patients>
<Patient name="Luca"/>
</Patients>
</Hospital>
</Hospitals>
</Database>
如果(比如)Luca也在JR患者名单中,那么你就会列出两家医院,即
<Patient name="Luca">
<Hospital name="JR"/>
<Hospital name="LondonGeneral"/>
</Patient>