在XSLT中添加缺少的XML元素需要什么?

时间:2012-03-30 19:19:36

标签: xml xslt transformation

我正在尝试将XML文件转换为更新版本。

我有以下Source XML

<?xml version="1.0" encoding="utf-8" ?>
<config>
  <section name="abc">
    <key name="key1">My Key One</key>
  </section>
  <section name="def">
    <key name="key2">My Key Two</key>
  </section>
</config>

转换看起来像这样......但是,目标实际上可能看起来像这样,所以如果已经存在,我不希望添加xyz部分:

<?xml version="1.0" encoding="utf-8" ?>
<config>
  <section name="abc">
    <key name="key1">My Key One</key>
  </section>
  <section name="def">
    <key name="key2">My Key Two</key>
  </section>
  <section name="xyz">
    <key name="key3">My Key Three</key>
  </section>
</config>

XSLT目前看起来像这样:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="config">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@*|text()|comment()|processing-instruction()">
<xsl:copy-of select="."/>
</xsl:template>

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

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

</xsl:stylesheet>

这似乎复制了存在的东西。如果它实际上丢失了,我怎么能让它添加我丢失的元素呢?

2 个答案:

答案 0 :(得分:4)

尝试这样的事情:

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

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

  <xsl:template match="config">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
      <xsl:if test="not(section/@name='xyz')">
        <section name="xyz">
          <key name="key3">My Key Three</key>
        </section>
      </xsl:if>
    </xsl:copy>    
  </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:2)

更短更简单(没有明确的条件指示)

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

 <xsl:template match="config[not(section[@name = 'xyz'])]">
  <config>
   <xsl:apply-templates select="node()|@*"/>
   <section name="xyz">
     <key name="key3">My Key Three</key>
   </section>
  </config>
 </xsl:template>
</xsl:stylesheet>

在提供的源XML文档上应用此转换时:

<config>
    <section name="abc">
        <key name="key1">My Key One</key>
    </section>
    <section name="def">
        <key name="key2">My Key Two</key>
    </section>
</config>

生成了想要的正确结果(添加了新的section):

<config>
   <section name="abc">
      <key name="key1">My Key One</key>
   </section>
   <section name="def">
      <key name="key2">My Key Two</key>
   </section>
   <section name="xyz">
      <key name="key3">My Key Three</key>
   </section>
</config>

应用于此XML文档时

<config>
   <section name="abc">
      <key name="key1">My Key One</key>
   </section>
   <section name="def">
      <key name="key2">My Key Two</key>
   </section>
   <section name="xyz">
      <key name="key3">My Key Three</key>
   </section>
</config>

再次产生了想要的结果(未添加新的部分,因为它已经存在):

<config>
   <section name="abc">
      <key name="key1">My Key One</key>
   </section>
   <section name="def">
      <key name="key2">My Key Two</key>
   </section>
   <section name="xyz">
      <key name="key3">My Key Three</key>
   </section>
</config>