如何添加标签?

How to add tags?

要更新的第一个 xml 文件“in.xml”:

<root attr="root">
  <xItem key="1" th="1">
    <m1 />
    <b attr3="j" attr4="x">
      <m4 />
      <m3 attr4="11" />
      <Chartr>
        <tag1 title="tag1"/>
        <Widget title="default1"/>
        <tag2 title="tag2"/>
      </Chartr>
      <Chartu>
        <tag3 title="tag3">
          <tag4 title="tag4"/>
        </tag3>
        <Widget title="default2">
          <default title="default3"/>
        </Widget>
        <tag5 title="tag5">
          <tag4 title="tag5"/>
        </tag5>
      </Chartu>
      <Itemz key="2" th="2">
        <d>
          <m6 />
          <Chartn>
            <Widget title="default4"/>
          </Chartn>
        </d>
        <m5 attr5="gd"/>
      </Itemz>
    </b>
    <Itemq key="3" th="3">
      <Itemt key="4" th="4">
        <Charto>
          <Widget title="default5">
            <default title="default6"/>
          </Widget>
        </Charto>
        <m6 />
      </Itemt>
      <m7 />
    </Itemq>
    <Chartd />
    <m2 />
  </xItem>
</root>

从中获取数据以更新第一个文件的第二个 xml 文件“updates.xml”:

<updates attr="updates">
  <xItem key="1">
    <b>
      <Chartr>
        <Widget title="update1" title1="update11">
          <update title="update2"/>
        </Widget>
      </Chartr>
      <Chartu>
        <Widget title="update3">
          <update title="update4" title4="update44"/>
        </Widget>
      </Chartu>
      <Itemz key="2">
        <d>
          <m6 />
          <Chartn/>
        </d>
      </Itemz>
    </b>
    <Itemq key="3">
      <Itemt key="4">
        <Charto>
          <Widget title="update5" x="23">
            <update1 title="update6" x="23"/>
            <update2 title="update7"/>
          </Widget>
        </Charto>
      </Itemt>
    </Itemq>
    <Chartd/>
  </xItem>
</updates>

update.xml 文件与输入文件的不同之处在于,它只包含那些作为 Widget 标签祖先的标签,并且缺少一些属性。在 XSLT1.0 转换之后,输入树被转移到输出树,替换了“updates.xml”文件中的 Widget 标签。如果输入文件中有 Widget 标签,但“updates.xml”文件中没有,则将输入文件中的 widget 标签传输到输出树。现在转换文件:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exslt="http://exslt.org/common"
  exclude-result-prefixes="exslt"
  version="1.0">
  <xsl:output method="xml"/>

  <xsl:key name="replacement" match="*[Widget]" use="local-name()"/>

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

  <xsl:template match="*[not(node())]|*[Widget]">
    <xsl:variable name="this" select="."/>
    <xsl:variable name="replacement">
      <xsl:for-each select="$updates">
        <xsl:copy-of select="key('replacement', local-name($this))"/>
      </xsl:for-each>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="exslt:node-set($replacement)/*">
        <xsl:copy-of select="$replacement"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:param name="updates" select="document('updates.xml')"/>

</xsl:stylesheet>

转换文件后:

<root attr="root">
  <xItem key="1" th="1">
    <m1 />
    <b attr3="j" attr4="x">
      <m4 />
      <m3 attr4="11" />
      <Chartr>
        <Widget title="update1" title1="update11">
          <update title="update2" />
        </Widget>
      </Chartr>
      <Chartu>
        <Widget title="update3">
          <update title="update4" title4="update44" />
        </Widget>
      </Chartu>
      <Itemz key="2" th="2">
        <d>
          <m6 />
          <Chartn>
            <Widget title="default4" />
          </Chartn>
        </d>
        <m5 attr5="gd" />
      </Itemz>
    </b>
    <Itemq key="3" th="3">
      <Itemt key="4" th="4">
        <Charto>
          <Widget title="update5" x="23">
            <update1 title="update6" x="23" />
            <update2 title="update7" />
          </Widget>
        </Charto>
        <m6 />
      </Itemt>
      <m7 />
    </Itemq>
    <Chartd />
    <m2 />
  </xItem>
</root>

如何确保输出文件还包含 Widget 标记的同级标记及其属性和后代标记,即 tag1、tag2、tag3、tag4、tag5,以便在 XSLT1.0 转换后输出文件如下所示:

<root attr="root">
  <xItem key="1" th="1">
    <m1 />
    <b attr3="j" attr4="x">
      <m4 />
      <m3 attr4="11" />
      <Chartr>
        <tag1 title="tag1"/>
        <Widget title="update1" title1="update11">
          <update title="update2" />
        </Widget>
        <tag2 title="tag2"/>
      </Chartr>
      <Chartu>
        <tag3 title="tag3">
          <tag4 title="tag4" />
        </tag3>
        <Widget title="update3">
          <update title="update4" title4="update44" />
        </Widget>
        <tag5 title="tag5">
          <tag4 title="tag5"/>
        </tag5>
      </Chartu>
      <Itemz key="2" th="2">
        <d>
          <m6 />
          <Chartn>
            <Widget title="default4" />
          </Chartn>
        </d>
        <m5 attr5="gd" />
      </Itemz>
    </b>
    <Itemq key="3" th="3">
      <Itemt key="4" th="4">
        <Charto>
          <Widget title="update5" x="23">
            <update1 title="update6" x="23" />
            <update2 title="update7" />
          </Widget>
        </Charto>
        <m6 />
      </Itemt>
      <m7 />
    </Itemq>
    <Chartd />
    <m2 />
  </xItem>
</root>

通过将上下文更改为实际的 Widget 并将其 parent-name 用作键,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exslt="http://exslt.org/common"
  exclude-result-prefixes="exslt"
  version="1.0">
  <xsl:output method="xml"/>
  
  <xsl:key name="replacement" match="Widget" use="local-name(parent::*)"/>
  
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="Widget">
    <xsl:variable name="parentName" select="local-name(parent::*)"/>
    <xsl:variable name="replacement">
      <xsl:for-each select="$updates">
        <xsl:copy-of select="key('replacement', $parentName)"/>
      </xsl:for-each>
    </xsl:variable>
    <xsl:choose>
      <xsl:when test="exslt:node-set($replacement)/*">
        <xsl:copy-of select="$replacement"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:copy-of select="."/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
  
  <xsl:param name="updates" select="document('updates.xml')"/>
  
</xsl:stylesheet>