XSLT:将XMS复制到XML并更新文件结构

XSLT:将XMS复制到XML并更新文件结构,xslt,xml-parsing,Xslt,Xml Parsing,我有一个包含元素的XML文件,它有两个子元素和。每个都有一个子元素,其名称指定为属性。每个医院都有一个属性名,例如:假设每个患者名正好包含在一个hospital元素中,则以下操作应该有效 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:key name="hospitalPatientByName" match="Hospital

我有一个包含元素
的XML文件,它有两个子元素
。每个
都有一个子元素
,其名称指定为属性。每个医院都有一个属性名,例如:
假设每个患者名正好包含在一个
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>
根据您的示例输入,这将产生

<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>

如果(比如)卢卡也在JR的病人名单上,那么你会得到两家医院的名单,即

<Patient name="Luca">
  <Hospital name="JR"/>
  <Hospital name="LondonGeneral"/>
</Patient>


这听起来很直截了当,但您是否可以编辑您的问题,以显示一个小而完整的XML示例(更改名称以保护无辜者)和您的预期输出,以确保对问题没有误解。谢谢同一名患者是否可以属于多家医院?如果是这样,您可能会更好地将关系表示为元素而不是属性。谢谢!这帮了大忙。@MichalB.Kovac很高兴能帮上忙,欢迎来到Stack Overflow。请注意,当你得到解决问题的答案时,最好将答案标记为“已接受”(使用左边的勾号),以便其他人一眼就能看出问题已经解决。
<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>
<Patient name="Luca">
  <Hospital name="JR"/>
  <Hospital name="LondonGeneral"/>
</Patient>