Как добавить элемент, создав его первым при необходимости - PullRequest
3 голосов
/ 08 марта 2012

Мне нужно добавить элементы к элементу, сначала создав его, если он еще не существует.

Мой желаемый конечный результат после добавления ABC и DEF:

<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Q/>
  <B>
    <string>ABC</string>
    <string>DEF</string>
  </B>
<A>

Я думал, что это можно сделать следующим образом:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <!-- Insert a B element if it doesn't exist. -->
  <xsl:template match="A[not(B)]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
        <B/>
    </xsl:copy>
  </xsl:template>

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

</xsl:stylesheet>

Если я начну со следующего, в котором уже существует, он работает нормально, возвращая результат выше:

<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
  <Q/>
  <B/>
</A>

Однако, если у меня нет , как показано ниже:

<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
  <Q/>
</A>

затем он создает , как показано ниже, но не вставляет ABC и DEF:

<?xml version="1.0" encoding="utf-8"?>
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org
  <Q/>
  <B/>
</A>

Итак, что мне не хватает? Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 08 марта 2012
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

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

    <!-- Insert a B element with string elements if it doesn't exist. -->
    <xsl:template match="A[not(B)]">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
            <B>
                <xsl:call-template name="add-strings"/>
            </B>
        </xsl:copy>
    </xsl:template>

    <!-- Add string elements to existing B if missing -->
    <xsl:template match="B[not(string)]">
        <xsl:copy>
            <xsl:call-template name="add-strings"/>
        </xsl:copy>
    </xsl:template>

    <!-- Add string elements to caller -->
    <xsl:template name="add-strings">
        <string>ABC</string>
        <string>DEF</string>
    </xsl:template>

</xsl:stylesheet>
1 голос
/ 08 марта 2012

Ответ Empo был очень близок, но если уже содержал элементов, новые не были добавлены. Я сделал два небольших изменения, которые решили, что:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

  <!-- Insert a B element with string elements if it doesn't exist. -->
  <xsl:template match="A[not(B)]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
      <B>
        <xsl:call-template name="add-strings"/>
      </B>
    </xsl:copy>
  </xsl:template>

  <!-- Add string elements to existing B element. -->
  <xsl:template match="B">  <!-- Whether there are <string>s or not. -->
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>  <!-- Keep existing <string>s. -->
      <xsl:call-template name="add-strings"/>
    </xsl:copy>
  </xsl:template>

  <!-- Add string elements to caller. -->
  <xsl:template name="add-strings">
    <string>ABC</string>
    <string>DEF</string>
  </xsl:template>

</xsl:stylesheet>
1 голос
/ 08 марта 2012

Вам также придется добавить дополнительные теги B, когда B не существует, как показано ниже:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>
  <!-- Identity transform -->
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <!-- Insert a B element if it doesn't exist. -->
  <xsl:template match="A[not(B)]">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
        <B>
           <string>ABC</string>
          <string>DEF</string>
       </B>
    </xsl:copy>
  </xsl:template>

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

</xsl:stylesheet>

применительно к

<?xml version="1.0" encoding="UTF-8"?>
<root>
<A>
  <Q/>
</A>
<A>
  <Q/>
  <B/>
</A>
</root>

это дает

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <A>
        <Q/>
        <B>
            <string>ABC</string>
            <string>DEF</string>
        </B>
    </A>
    <A>
        <Q/>
        <B>
            <string>ABC</string>
            <string>DEF</string>
        </B>
    </A>
</root>
...