Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 使所有元素的属性一致_Xml_Xslt - Fatal编程技术网

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

我有一个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="" 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(/@*)