Xml 使所有元素的属性一致
我有一个XML文件,其中所有元素的属性都不一致Xml 使所有元素的属性一致,xml,xslt,Xml,Xslt,我有一个XML文件,其中所有元素的属性都不一致 <Elem1 Attrib1="1" Attrib2="2"/> <Elem2 Attrib1="21" Attrib3="23"/> <Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/> <Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/> <Elem2 Attrib1="21" Attrib2
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
我想转换此文件,以便所有元素都具有相同数量的属性,如下所示
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
这可以通过XSLT实现吗?当转换
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Elem1|Elem2|Elem3">
<xsl:copy>
<xsl:if test="@Attrib1"><xsl:attribute name="Attrib1"><xsl:value-of select="@Attrib1"/></xsl:attribute></xsl:if>
<xsl:if test="not(@Attrib1)"><xsl:attribute name="Attrib1"></xsl:attribute></xsl:if>
<xsl:if test="@Attrib2"><xsl:attribute name="Attrib2"><xsl:value-of select="@Attrib2"/></xsl:attribute></xsl:if>
<xsl:if test="not(@Attrib2)"><xsl:attribute name="Attrib2"></xsl:attribute></xsl:if>
<xsl:if test="@Attrib3"><xsl:attribute name="Attrib3"><xsl:value-of select="@Attrib3"/></xsl:attribute></xsl:if>
<xsl:if test="not(@Attrib3)"><xsl:attribute name="Attrib3"></xsl:attribute></xsl:if>
<xsl:if test="@Attrib4"><xsl:attribute name="Attrib4"><xsl:value-of select="@Attrib4"/></xsl:attribute></xsl:if>
<xsl:if test="not(@Attrib4)"><xsl:attribute name="Attrib4"></xsl:attribute></xsl:if>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在下面的XML上运行
<test>
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
</test>
提供所需的输出
<?xml version='1.0' ?>
<test>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
</test>
<doc>
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
<doc>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
有很多可能的解决方案。 这里有一点简单,假设您关心的属性列表是众所周知的:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Elem1|Elem2|Elem3">
<xsl:copy >
<xsl:attribute name="Attrib1">
<xsl:value-of select="@Attrib1"/>
</xsl:attribute>
<xsl:attribute name="Attrib2">
<xsl:value-of select="@Attrib2"/>
</xsl:attribute>
<xsl:attribute name="Attrib3">
<xsl:value-of select="@Attrib3"/>
</xsl:attribute>
<xsl:attribute name="Attrib4">
<xsl:value-of select="@Attrib4"/>
</xsl:attribute>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<test>
<xsl:apply-templates />
</test>
</xsl:template>
</xsl:stylesheet>
这里有一个XSLT2.0选项。它可能被修改为适用于XSLT1.0 XML输入
<?xml version='1.0' ?>
<test>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
</test>
<doc>
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
<doc>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
XSLT2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="attrs" select="//@*/name()"/>
<xsl:key name="kAttrs" match="@*" use="name()"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@*]">
<xsl:copy>
<xsl:for-each select="key('kAttrs',$attrs)">
<xsl:attribute name="{name(.)}"/>
</xsl:for-each>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出
<?xml version='1.0' ?>
<test>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
</test>
<doc>
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
<doc>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/>
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/>
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
这里有另一个XSLT2.0选项,它只适用于2.0(这个选项也快了很多):
这将返回与上面相同的结果(w/相同的输入)。这里是XSLT1.0中的通用方法。它包含一些额外的逻辑,以确保所有属性的顺序相同:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:key name="kAttr" match="@*" use="name()" />
<xsl:variable name="distinctAttr"
select="//@*[generate-id() =
generate-id(key('kAttr', name())[1])]" />
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*/*">
<xsl:copy>
<xsl:apply-templates select="$distinctAttr | @*">
<xsl:sort select="name()" />
<xsl:with-param name="parent" select="." />
</xsl:apply-templates>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:param name="parent" select="/.." />
<xsl:if test="not($parent) or
count(.. | $parent) = 1 or
not($parent/@*[name() = name(current())])">
<xsl:attribute name="{name()}">
<xsl:value-of select="substring(., 1, string-length() *
(2 - count($parent | ..)))"/>
</xsl:attribute>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
在该输入上运行时:
<doc>
<Elem1 Attrib1="1" Attrib2="2"/>
<Elem2 Attrib1="21" Attrib3="23"/>
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/>
</doc>
结果是:
<doc>
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4="" />
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4="" />
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34" />
</doc>
我认为这是可能的。你尝试过什么&你在哪里被击中了?这是一个棘手的问题。添加具有空值的所有属性,并将其替换为现有属性。我喜欢它我得到了下面的“error Expected end of the expression,found'('”位于“@user2071531”行-您确定没有使用XSLT 1.0吗?在1.0中,您必须执行name(/@*)
。