如何删除多余的标签?
How to remove extra tag?
要更新的第一个 xml 文件:
<Conf key="11" title="tit">
<Item key="1" >
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="11" description="11" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="22" description="22" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="33" description="33" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="44" description="44" />
</Am>
</Item>
</Conf>
从中获取数据以更新第一个文件的第二个 xml 文件“updates.xml”:
<Profile title="u">
<Item key="1">
<Vol>
<Widget title="AA"/>
</Vol>
<Am>
<Widget title="BB" description="BB" />
</Am>
</Item>
<Item key="2">
<Vol>
<Widget title="CC" description="CC" />
</Vol>
<Am>
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Profile>
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:param name="updates" select="document('updates.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:stylesheet>
转换文件后:
<?xml version="1.0" encoding="utf-8"?>
<Conf key="11" title="tit">
<Item key="1">
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="AA" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="BB" description="BB" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="AA" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="BB" description="BB" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Conf>
如何保证XSLT1.0改造后的输出文件没有多余的Widget标签,输出文件是这样的:
<?xml version="1.0" encoding="utf-8"?>
<Conf key="11" title="tit">
<Item key="1">
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="AA" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="BB" description="BB" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Conf>
我会这样处理,不需要使用 exslt:node-set()
扩展函数。
创建一个复合键,它使用 Item
的 @key
和 Widget
父元素的 local-name()
。使用该复合键值从用于将上下文切换到 updates.xml
文档的 xs:for-each
中的 $updates
中查找相应的 Widget
。
<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" indent="yes"/>
<xsl:variable name="updates" select="document('updates.xml')"/>
<xsl:key name="replacement" match="Widget" use="concat(../../@key, local-name(..))"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Widget">
<xsl:variable name="key" select="concat(../../@key, local-name(..))"/>
<xsl:variable name="replacement">
<xsl:for-each select="$updates">
<xsl:copy-of select="key('replacement', $key)"/>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="$replacement">
<xsl:copy-of select="$replacement"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
要更新的第一个 xml 文件:
<Conf key="11" title="tit">
<Item key="1" >
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="11" description="11" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="22" description="22" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="33" description="33" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="44" description="44" />
</Am>
</Item>
</Conf>
从中获取数据以更新第一个文件的第二个 xml 文件“updates.xml”:
<Profile title="u">
<Item key="1">
<Vol>
<Widget title="AA"/>
</Vol>
<Am>
<Widget title="BB" description="BB" />
</Am>
</Item>
<Item key="2">
<Vol>
<Widget title="CC" description="CC" />
</Vol>
<Am>
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Profile>
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:param name="updates" select="document('updates.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:stylesheet>
转换文件后:
<?xml version="1.0" encoding="utf-8"?>
<Conf key="11" title="tit">
<Item key="1">
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="AA" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="BB" description="BB" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="AA" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="BB" description="BB" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Conf>
如何保证XSLT1.0改造后的输出文件没有多余的Widget标签,输出文件是这样的:
<?xml version="1.0" encoding="utf-8"?>
<Conf key="11" title="tit">
<Item key="1">
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="AA" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="BB" description="BB" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Conf>
我会这样处理,不需要使用 exslt:node-set()
扩展函数。
创建一个复合键,它使用 Item
的 @key
和 Widget
父元素的 local-name()
。使用该复合键值从用于将上下文切换到 updates.xml
文档的 xs:for-each
中的 $updates
中查找相应的 Widget
。
<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" indent="yes"/>
<xsl:variable name="updates" select="document('updates.xml')"/>
<xsl:key name="replacement" match="Widget" use="concat(../../@key, local-name(..))"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Widget">
<xsl:variable name="key" select="concat(../../@key, local-name(..))"/>
<xsl:variable name="replacement">
<xsl:for-each select="$updates">
<xsl:copy-of select="key('replacement', $key)"/>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="$replacement">
<xsl:copy-of select="$replacement"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>