XSL - дубликат дочернего родительского узла - PullRequest
0 голосов
/ 27 августа 2018

После поиска узла с тем же именем в другой структуре и замены его значения, как я могу продублировать родительский узел совпадающего?

Можно ли установить ключ для каждого родителя ребенка в шаблоне?

Из этого

<Message>
<XMLNSC>
    <MaXML>
        <Rule>
            <A>RuleA</A>
            <D>RuleD</D>
        </Rule>
        <Body>
            <A>valA</A>
            <B>valB</B>
            <C>
                <D>valD</D>
            </C>
        </Body>
    </MaXML>
</XMLNSC>

На это

<Message>
<XMLNSC>
    <MaXML>
        <Rule>
            <A>RuleA</A>
            <D>RuleD</D>
        </Rule>
        <Body>
            <A>RuleA</A>
            <A>RuleA</A>
            <B>valB</B>
            <C>
                <D>RuleD</D>
                <D>RuleD</D>
            </C>
            <C>
                <D>RuleD</D>
                <D>RuleD</D>
            </C>
        </Body>
        <Body>
            <A>RuleA</A>
            <A>RuleA</A>
            <B>valB</B>
            <C>
                <D>RuleD</D>
                <D>RuleD</D>
            </C>
            <C>
                <D>RuleD</D>
                <D>RuleD</D>
            </C>
        </Body>
    </MaXML>
</XMLNSC>

Мой XSLT, https://xsltfiddle.liberty -development.net / pPqsHTK / 5

1 Ответ

0 голосов
/ 27 августа 2018

Если вы напишите шаблон для тех потомков MaXML, у которых есть дочерний элемент с соответствием ключа, вы можете просто дважды использовать шаблон идентификатора для этих элементов-потомков, у меня было явное исключение элементов Rule, тогда:

<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:strip-space elements="*"/>
  <xsl:output indent="yes"/>

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

  <xsl:key name="ref" match="MaXML/Rule/*" use="concat(generate-id(ancestor::MaXML), '|', name())"/>

  <xsl:template match="MaXML//*[not(self::Rule)][*[key('ref', concat(generate-id(ancestor::MaXML), '|', name()))]]">
      <xsl:call-template name="identity"/>
      <xsl:call-template name="identity"/>
  </xsl:template>

  <xsl:template match="Body//*[key('ref', concat(generate-id(ancestor::MaXML), '|', name()))]">
      <xsl:copy>
          <xsl:value-of select="key('ref', concat(generate-id(ancestor::MaXML), '|', name()))"/>
      </xsl:copy>

      <!-- duplicate matched node -->
        <xsl:element name="{name()}">
            <xsl:value-of select="key('ref', concat(generate-id(ancestor::MaXML), '|', name()))"/>
        </xsl:element>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / pPqsHTK / 6

С XSLT 3 это немного проще:

  <xsl:template match="MaXML//*[not(self::Rule)][*[key('ref', node-name(), ancestor::MaXML)]]">
      <xsl:next-match/>
      <xsl:next-match/>
  </xsl:template>

https://xsltfiddle.liberty -development.net / pPqsHTK / 8

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