使用密钥匹配引用XSLT 1.0中的另一个节点

时间:2018-03-15 14:41:10

标签: xml xslt xslt-1.0

我希望将单个XML表与两个“部分”信息,“Notes”和“Encounters”结合起来。每个笔记都有一个扩展ID ,每次遭遇都有一个扩展ID

数据设置如下:

<Root>
  <Notes>
    <Note>
        <NoteText>
            <p>Text Paragraph 1</p>
            <p>Text Paragraph 2</p>
        </NoteText>
        <ExtensionID>123456</ExtensionID>
    </Note>
    <Note>
        <NoteText>
            <p>Text Paragraph 3</p>
        </NoteText>
        <ExtensionID>123456</ExtensionID>
    </Note>
    <Note>
        <NoteText>
            <p>Text Paragraph 4</p>
            <p>Text Paragraph 5</p>
        </NoteText>
        <ExtensionID>789012</ExtensionID>
    </Note>
  </Notes>
    <Encounter>
        <ExtensionID>123456</ExtensionID>
        <Date>2017-01-02</Date>
        <Author>Dr. George Smith</Author>
    </Encounter>
        <ExtensionID>798012</ExtensionID>
        <Date>2015-10-20</Date>
        <Author>Jenny Jones</Author>
    <Encounter>
<Root>

我想得到以下输出:

<Import>
    <Notes>
        <Note ExtensionID="123456">
            <NoteText>
                <p>Text Paragraph 1</p>
                <p>Text Paragraph 2</p>
                <p>Text Paragraph 3</p>
            <NoteText>
            <Author>Dr. George Smith</Author>
            <Date>2015-10-20</Date>
        </Note>
        <Note ExtensionID="789012">
            <NoteText>
                <p>Text Paragraph 4</p>
                <p>Text Paragraph 5</p>
            <NoteText>
            <Author>Jenny Jones</Author>
            <Date>2015-10-20</Date>
        </Note>
    <Notes>
<Import>

My Current XSLT如下:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/">

      <Import>

      <Notes>
        <xsl:apply-templates select="Root/Notes"/>
      </Notes>
  </Import>
  </xsl:template>

  <xsl:key name ="ExtID" match="Note" use="ExtensionID"/>


  <xsl:template match="Root/Notes">
    <xsl:for-each select="Note[count(.|key('ExtID',ExtensionID)[1]) = 1]">
      <Note>
        <xsl:attribute name="ExtensionID">

          <xsl:value-of select="ExtensionID"/>

        </xsl:attribute>
        <xsl:for-each select="key('ExtID',ExtensionID)">
          <xsl:copy-of select="NoteText"/>
        </xsl:for-each>

      <xsl:for-each select="../../Encounters/Encounter[ExtensionID=key('ExtID',ExtensionID)]">
        <Author>
          <xsl:value-of select="Provider"/>        
        </Author>
        <Date>
            <xsl:value-of select="Date" />
        </Date>

      </xsl:for-each>
    </Note>
    </xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

第一部分主要是通过扩展ID进行分组,但它是我正在努力解决的相关遭遇信息。

我注意到的是它甚至没有进入for-each循环“../../Encounters/Encounter[ExtensionID=key('ExtID',ExtensionID)]”。我几乎肯定我不能做我想做的事情:像某种形式的“不可变”一样使用密钥,但我不确定下一步该尝试什么。

请注意:我受到我们在办公室使用的软件XSLT 1.0的限制。我无法访问2.0功能,也无法安装/升级或使用与Visual Studio中不同的引擎。

2 个答案:

答案 0 :(得分:2)

这条线确实存在问题......

<xsl:for-each select="../../Encounters/Encounter[ExtensionID=key('ExtID',ExtensionID)]">

忽略您在XML中没有Encounters的事实,&#34;键&#34;当您只想要当前Note的{​​{1}}值时,将返回ExtensionID个节点。所以应该是这个......

Note

或者,如果您定义另一个这样的键......

<xsl:for-each select="../../Encounters/Encounter[ExtensionID=current()/ExtensionID]">

然后你可以这样做......

<xsl:key name="EncID" match="Encounter" use="ExtensionID"/>

试试这个XSLT ....

<xsl:for-each select="key('EncID', ExtensionID)">

也许你应该扭转XSLT的逻辑呢?不要对<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> <xsl:output method="xml" indent="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="/"> <Import> <Notes> <xsl:apply-templates select="Root/Notes"/> </Notes> </Import> </xsl:template> <xsl:key name ="ExtID" match="Note" use="ExtensionID"/> <xsl:key name="EncID" match="Encounter" use="ExtensionID"/> <xsl:template match="Notes"> <xsl:for-each select="Note[count(.|key('ExtID',ExtensionID)[1]) = 1]"> <Note ExtensionID="{ExtensionID}"> <NoteText> <xsl:copy-of select="key('ExtID',ExtensionID)/NoteText/*"/> </NoteText> <xsl:for-each select="key('EncID', ExtensionID)"> <Author> <xsl:value-of select="Author"/> </Author> <Date> <xsl:value-of select="Date" /> </Date> </xsl:for-each> </Note> </xsl:for-each> </xsl:template> </xsl:stylesheet> 元素进行分组,而是先获取Note元素,然后使用键获取它们的注释....

Encounter

答案 1 :(得分:1)

为交叉引用定义第二个键:

<xsl:key name="ref" match="Encounter" use="ExtensionID"/>

然后你可以选择

  <xsl:for-each select="key('ref',ExtensionID)">
    <Author>
      <xsl:value-of select="Provider"/>        
    </Author>
    <Date>
        <xsl:value-of select="Date" />
    </Date>

  </xsl:for-each>

而不是

  <xsl:for-each select="../../Encounters/Encounter[ExtensionID=key('ExtID',ExtensionID)]">
    <Author>
      <xsl:value-of select="Provider"/>        
    </Author>
    <Date>
        <xsl:value-of select="Date" />
    </Date>

  </xsl:for-each>