Слияние данных из узла XML в другой узел с использованием XSLT - PullRequest
2 голосов
/ 12 февраля 2011

Используя XSLT, я пытаюсь выяснить, как объединить / обновить данные в наборе узлов с данными из другого набора узлов.Узлы имеют одинаковую схему, но разных родителей.Данные должны быть объединены на основе общего родительского атрибута.В приведенном ниже примере данные копируются из принципала в драйвер.Может кто-нибудь помочь мне здесь?

Входной файл:

<Info>
  <Principal id="Insured">
    <PersonName>
      <GivenName>Jane</GivenName>
      <OtherGivenName>A</OtherGivenName>
      <Surname>Doe</Surname>
    </PersonName>
    <PersonInfo>
      <BirthDate>01-01-1980</BirthDate>
      <MaritalStatus>M</MaritalStatus>
    </PersonInfo>
    <PrincipalInfo></PrincipalInfo>
  </Principal>
  <Policy>
    <Driver id="Insured">
      <PersonName>
        <GivenName>Jane</GivenName>
        <Surname>Smith</Surname>
      </PersonName>
      <PersonInfo>
        <BirthDate>01-01-1980</BirthDate>
        <MaritalStatus>S</MaritalStatus>
        <Occupation>Manager</Occupation>
      </PersonInfo>
    </Driver>
    <PolicyInfo></PolicyInfo>
  </Policy>
</Info>

Желаемый результат:

<Info>
  <Principal id="Insured">
    <PersonName>
      <GivenName>Jane</GivenName>
      <OtherGivenName>A</OtherGivenName>
      <Surname>Doe</Surname>
    </PersonName>
    <PersonInfo>
      <BirthDate>01-01-1980</BirthDate>
      <MaritalStatus>M</MaritalStatus>
    </PersonInfo>
    <PrincipalInfo></PrincipalInfo>
  </Principal>
  <Policy>
    <Driver id="Insured">
      <PersonName>
        <GivenName>Jane</GivenName>
        <OtherGivenName>A</OtherGivenName>
        <Surname>Doe</Surname>
      </PersonName>
      <PersonInfo>
        <BirthDate>01-01-1980</BirthDate>
        <MaritalStatus>M</MaritalStatus>
        <Occupation>Manager</Occupation>
      </PersonInfo>
    </Driver>
    <PolicyInfo></PolicyInfo>
  </Policy>
</Info>

1 Ответ

2 голосов
/ 12 февраля 2011

Вот полное решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kPrincipalById" match="Principal"
  use="@id"/>

 <xsl:key name="kPrincipalChild" match="Principal/*/*"
  use="concat(../../@id, name())"/>

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

 <xsl:template match="Driver/*">
  <xsl:variable name="vPrincipal"
   select="key('kPrincipalById', ../@id)"/>

   <xsl:copy>
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates select=
     "$vPrincipal/*[name()=name(current())]/*"/>
    <xsl:apply-templates select=
     "*[not(key('kPrincipalChild',
                 concat(../../@id,name())
                 )
            )
        ]"/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML:

<Info>
    <Principal id="Insured">
        <PersonName>
            <GivenName>Jane</GivenName>
            <OtherGivenName>A</OtherGivenName>
            <Surname>Doe</Surname>
        </PersonName>
        <PersonInfo>
            <BirthDate>01-01-1980</BirthDate>
            <MaritalStatus>M</MaritalStatus>
        </PersonInfo>
        <PrincipalInfo></PrincipalInfo>
    </Principal>
    <Policy>
        <Driver id="Insured">
            <PersonName>
                <GivenName>Jane</GivenName>
                <Surname>Smith</Surname>
            </PersonName>
            <PersonInfo>
                <BirthDate>01-01-1980</BirthDate>
                <MaritalStatus>S</MaritalStatus>
                <Occupation>Manager</Occupation>
            </PersonInfo>
        </Driver>
        <PolicyInfo></PolicyInfo>
    </Policy>
</Info>

желаемый, правильный результат получается:

<Info>
   <Principal id="Insured">
      <PersonName>
         <GivenName>Jane</GivenName>
         <OtherGivenName>A</OtherGivenName>
         <Surname>Doe</Surname>
      </PersonName>
      <PersonInfo>
         <BirthDate>01-01-1980</BirthDate>
         <MaritalStatus>M</MaritalStatus>
      </PersonInfo>
      <PrincipalInfo/>
   </Principal>
   <Policy>
      <Driver id="Insured">
         <PersonName>
            <GivenName>Jane</GivenName>
            <OtherGivenName>A</OtherGivenName>
            <Surname>Doe</Surname>
         </PersonName>
         <PersonInfo>
            <BirthDate>01-01-1980</BirthDate>
            <MaritalStatus>M</MaritalStatus>
            <Occupation>Manager</Occupation>
         </PersonInfo>
      </Driver>
      <PolicyInfo/>
   </Policy>
</Info>

Объяснение

  1. Правило идентификации / template копирует каждый узел"как есть". Использование и переопределение правила идентификации является наиболее фундаментальным и мощным шаблоном проектирования XSLT.

  2. Существует только один дополнительный шаблон, который переопределяет правило идентификации для дочерних элементов Driver. Он копирует (и эффективно заменяет одноименные элементы grand-child Driver на соответствующие) элементы grand-child Principal. Затем он все еще обрабатывает (копирует) те элементы потомков Driver, которые не имеют соответствующих элементов потомков Principal

  3. Для удобного доступа к Principal и его внукам - по id и id ++ name (), есть две клавиши , определенные и используемые.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...