如何简化相同的代码块?
How to simplify identical blocks of code?
输入xml文件:
<Config>
<Fix title="title" description="description" React="200" Lock="E0" Hold="50">
<Name type="type" value="value" Hold="50">
<Image select="2" readonly="false" />
</Name>
</Fix>
</Config>
从中获取输入文件更新的“updates.xml”文件 - 带有 const="?" 的 Lock、React 和 Hold 标签属性:
<Macro>
<Item key="Element">
<tag1 title="title1" description="description1" />
<tag2 title="title2" description="description2" />
<tag3 title="title3" description="description3" />
</Item>
<Item key="Attribute">
<Lock title="title4" const="?" description="description4" />
<React title="title5" const="?" description="description5" />
<Hold title="title6" const="?" description="description6" />
</Item>
</Macro>
如果输入文件包含“updates.xml”文件中的标签,则将“updates.xml”文件中的属性复制到其中。此外,如果输入文件中的标签具有 Lock、React 或 Hold 属性,则在转换后,这些属性成为子标签,而不是属性,并且输入文件中的 Lock、React 或 Hold 属性的值成为分别为转换后文件的 Lock、React 或 Hold 标签的 const 属性值。 XSLT1.0 转换后的文件应该是这样的:
<Config>
<Fix title="title" description="description">
<Lock const="E0" title="title4" description="description4" />
<React const="200" title="title5" description="description5" />
<Hold const="50" title="title6" description="description6" />
<Name type="type" value="value">
<Hold const="50" title="title6" description="description6" />
<Image select="2" readonly="false" />
</Name>
</Fix>
</Config>
XSLT1.0 转换文件具有三个相同的 Lock、React 或 Hold 标签选择代码块:
<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" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" />
<xsl:variable name="updates" select="document('updates.xml')"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:variable name="name" select="name()"/>
<xsl:apply-templates select="$updates//*[name(.) = $name]/@*"/>
<xsl:apply-templates select="@*"/>
<xsl:choose>
<xsl:when test="self::node()[@Lock]">
<Lock const="{@Lock}">
<xsl:copy-of select="$updates//Lock/@*[name(.) != 'const']"/>
</Lock>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@Lock]">
<Lock>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@Lock"/>
</xsl:attribute>
<xsl:copy-of select="$updates//Lock/@*[name(.) != 'const']"/>
</Lock>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="self::node()[@React]">
<React const="{@React}">
<xsl:copy-of select="$updates//React/@*[name(.) != 'const']"/>
</React>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@React]">
<React>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@React"/>
</xsl:attribute>
<xsl:copy-of select="$updates//React/@*[name(.) != 'const']"/>
</React>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="self::node()[@Hold]">
<Hold const="{@Hold}">
<xsl:copy-of select="$updates//Hold/@*[name(.) != 'const']"/>
</Hold>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@Hold]">
<Hold>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@Hold"/>
</xsl:attribute>
<xsl:copy-of select="$updates//Hold/@*[name(.) != 'const']"/>
</Hold>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="@Lock" />
<xsl:template match="@React" />
<xsl:template match="@Hold" />
</xsl:stylesheet>
如何将 Lock、React 或 Hold 标签的三个选择块转换为一个?
您可以参数化模板并调用它或apply-templates(使用模式):
<xsl:template match="*">
<xsl:copy>
<xsl:variable name="name" select="name()"/>
<xsl:apply-templates select="$updates//*[name(.) = $name]/@*"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="." mode="compare">
<xsl:with-param name="att" select="'Lock'"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="compare">
<xsl:with-param name="att" select="'React'"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="compare">
<xsl:with-param name="att" select="'Hold'"/>
</xsl:apply-templates>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="compare">
<xsl:param name="att"/>
<xsl:variable name="name" select="name()"/>
<xsl:choose>
<xsl:when test="self::node()[@*[name() = $att]]">
<xsl:element name="{$att}">
<xsl:attribute name="const">
<xsl:value-of select="@*[name() = $att]"/>
</xsl:attribute>
<xsl:copy-of select="$updates//*[name() = $att]/@*[name(.) != 'const']"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@*[name() = $att]]">
<Lock>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@*[name() = $att]"/>
</xsl:attribute>
<xsl:copy-of select="$updates//*[name() = $att]/@*[name(.) != 'const']"/>
</Lock>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这样代码不一定会变得更易读。
输入xml文件:
<Config>
<Fix title="title" description="description" React="200" Lock="E0" Hold="50">
<Name type="type" value="value" Hold="50">
<Image select="2" readonly="false" />
</Name>
</Fix>
</Config>
从中获取输入文件更新的“updates.xml”文件 - 带有 const="?" 的 Lock、React 和 Hold 标签属性:
<Macro>
<Item key="Element">
<tag1 title="title1" description="description1" />
<tag2 title="title2" description="description2" />
<tag3 title="title3" description="description3" />
</Item>
<Item key="Attribute">
<Lock title="title4" const="?" description="description4" />
<React title="title5" const="?" description="description5" />
<Hold title="title6" const="?" description="description6" />
</Item>
</Macro>
如果输入文件包含“updates.xml”文件中的标签,则将“updates.xml”文件中的属性复制到其中。此外,如果输入文件中的标签具有 Lock、React 或 Hold 属性,则在转换后,这些属性成为子标签,而不是属性,并且输入文件中的 Lock、React 或 Hold 属性的值成为分别为转换后文件的 Lock、React 或 Hold 标签的 const 属性值。 XSLT1.0 转换后的文件应该是这样的:
<Config>
<Fix title="title" description="description">
<Lock const="E0" title="title4" description="description4" />
<React const="200" title="title5" description="description5" />
<Hold const="50" title="title6" description="description6" />
<Name type="type" value="value">
<Hold const="50" title="title6" description="description6" />
<Image select="2" readonly="false" />
</Name>
</Fix>
</Config>
XSLT1.0 转换文件具有三个相同的 Lock、React 或 Hold 标签选择代码块:
<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" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes" />
<xsl:variable name="updates" select="document('updates.xml')"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:variable name="name" select="name()"/>
<xsl:apply-templates select="$updates//*[name(.) = $name]/@*"/>
<xsl:apply-templates select="@*"/>
<xsl:choose>
<xsl:when test="self::node()[@Lock]">
<Lock const="{@Lock}">
<xsl:copy-of select="$updates//Lock/@*[name(.) != 'const']"/>
</Lock>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@Lock]">
<Lock>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@Lock"/>
</xsl:attribute>
<xsl:copy-of select="$updates//Lock/@*[name(.) != 'const']"/>
</Lock>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="self::node()[@React]">
<React const="{@React}">
<xsl:copy-of select="$updates//React/@*[name(.) != 'const']"/>
</React>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@React]">
<React>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@React"/>
</xsl:attribute>
<xsl:copy-of select="$updates//React/@*[name(.) != 'const']"/>
</React>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="self::node()[@Hold]">
<Hold const="{@Hold}">
<xsl:copy-of select="$updates//Hold/@*[name(.) != 'const']"/>
</Hold>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@Hold]">
<Hold>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@Hold"/>
</xsl:attribute>
<xsl:copy-of select="$updates//Hold/@*[name(.) != 'const']"/>
</Hold>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="@Lock" />
<xsl:template match="@React" />
<xsl:template match="@Hold" />
</xsl:stylesheet>
如何将 Lock、React 或 Hold 标签的三个选择块转换为一个?
您可以参数化模板并调用它或apply-templates(使用模式):
<xsl:template match="*">
<xsl:copy>
<xsl:variable name="name" select="name()"/>
<xsl:apply-templates select="$updates//*[name(.) = $name]/@*"/>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="." mode="compare">
<xsl:with-param name="att" select="'Lock'"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="compare">
<xsl:with-param name="att" select="'React'"/>
</xsl:apply-templates>
<xsl:apply-templates select="." mode="compare">
<xsl:with-param name="att" select="'Hold'"/>
</xsl:apply-templates>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="compare">
<xsl:param name="att"/>
<xsl:variable name="name" select="name()"/>
<xsl:choose>
<xsl:when test="self::node()[@*[name() = $att]]">
<xsl:element name="{$att}">
<xsl:attribute name="const">
<xsl:value-of select="@*[name() = $att]"/>
</xsl:attribute>
<xsl:copy-of select="$updates//*[name() = $att]/@*[name(.) != 'const']"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:if test="($updates//*[name(.) = $name])[@*[name() = $att]]">
<Lock>
<xsl:attribute name="const">
<xsl:value-of select="$updates//*[name(.) = $name]/@*[name() = $att]"/>
</xsl:attribute>
<xsl:copy-of select="$updates//*[name() = $att]/@*[name(.) != 'const']"/>
</Lock>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
这样代码不一定会变得更易读。