-1
<Rootnode>
    <Properties Attribute ="xxx">
        <Type>1</Type>
        <Size>10</Size>
    </Properties>
    <Other>
        <blah>h</blah>
    </Other>
    <Other2>
        <blah>h</blah>
    </Other2>
    <Properties Attribute ="xxx">
        <xType>5</xType>
        <xSize>10</xSize>
    </Properties>
    <Items>
       <Item4>8</Item4>
    </Items>
    <Items>
       <Item6>8</Item6>
    </Items>
    <Properties Attribute ="xxx">
        <zType>1</zType>
        <zSize>10</zSize>
    </Properties>
    <Items place="UK">
       <Item1>8</Item1>
    </Items>
 </Rootnode>

现在我想要的是只包括属性和项目。如果属性的名称和值相同,最好将属性和项目组连接在一起,并根据属性对属性和项目进行排序,并按字母顺序对两者的子节点进行排序。到目前为止,我已经达到了一个空白;(

所需的输出与 ABach 显示的差不多。虽然我忘记提到的一件事是每个属性或项目上可能还有其他属性,并且我知道我希望排序的属性的名称。我可以很容易地修改。

即,所需的输出

<?xml version="1.0"?>
<Rootnode>
  <Properties Attribute="xxx">
    <Size>10</Size>
    <Type>1</Type>
    <xSize>10</xSize>
    <xType>5</xType>
    <zSize>10</zSize>
    <zType>1</zType>
  </Properties>
  <Items>
    <Item4>8</Item4>
    <Item6>8</Item6>
  </Items>
  <Items place="UK">
    <Item1>8</Item1>
  </Items>
</Rootnode>

并为到目前为止我的努力而道歉......我最终陷入了一个正确的混乱并且认为这不会有太大帮助......我对这些东西很陌生:)

4

2 回答 2

2

正如@LarsH 已经指出的那样,由于没有向我们展示预期的输出 XML,我们只能猜测您真正想要什么。也就是说,这是我对 XSLT 1.0 解决方案的尝试。

当这个 XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
  <xsl:output omit-xml-declaration="no" indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:key
    name="PropertiesByAttributeNameVal"
    match="Properties"
    use="concat(name(@*[1]), '+', @*[1])" />

  <xsl:key
    name="ItemsByAttributeNameVal" 
    match="Items"
    use="concat(name(@*[1]), '+', @*[1])" />

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

  <xsl:template match="Rootnode">
    <Rootnode>
      <xsl:apply-templates 
        select="Properties[
          generate-id() = 
          generate-id(key(
            'PropertiesByAttributeNameVal',
             concat(name(@*[1]), '+', @*[1]))[1])]">
        <xsl:with-param name="pKeyName"
          select="'PropertiesByAttributeNameVal'" />
        <xsl:sort select="concat(name(@*[1]), '+', @*[1])" />
      </xsl:apply-templates>
      <xsl:apply-templates
        select="Items[
          generate-id() = 
          generate-id(key(
            'ItemsByAttributeNameVal',
            concat(name(@*[1]), '+', @*[1]))[1])]">
        <xsl:with-param name="pKeyName"
          select="'ItemsByAttributeNameVal'" />
        <xsl:sort select="concat(name(@*[1]), '+', @*[1])" />
      </xsl:apply-templates>
    </Rootnode>
  </xsl:template>

  <xsl:template match="Properties|Items">
    <xsl:param name="pKeyName" />
    <xsl:copy>
      <xsl:apply-templates select="@*" />
      <xsl:apply-templates
        select="key($pKeyName, concat(name(@*[1]), '+', @*[1]))/*">
        <xsl:sort select="name()" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

...针对提供的 XML 运行:

<Rootnode>
  <Properties Attribute="xxx">
    <Type>1</Type>
    <Size>10</Size>
  </Properties>
  <Other>
    <blah>h</blah>
  </Other>
  <Other2>
    <blah>h</blah>
  </Other2>
  <Properties Attribute="xxx">
    <xType>5</xType>
    <xSize>10</xSize>
  </Properties>
  <Items>
    <Item4>8</Item4>
  </Items>
  <Items>
    <Item6>8</Item6>
  </Items>
  <Properties Attribute="xxx">
    <zType>1</zType>
    <zSize>10</zSize>
  </Properties>
  <Items place="UK">
    <Item1>8</Item1>
  </Items>
</Rootnode>

...我猜是生成了正确的输出 XML:

<?xml version="1.0"?>
<Rootnode>
  <Properties Attribute="xxx">
    <Size>10</Size>
    <Type>1</Type>
    <xSize>10</xSize>
    <xType>5</xType>
    <zSize>10</zSize>
    <zType>1</zType>
  </Properties>
  <Items>
    <Item4>8</Item4>
    <Item6>8</Item6>
  </Items>
  <Items place="UK">
    <Item1>8</Item1>
  </Items>
</Rootnode>

请注意,如果针对稍微修改的 XML 文档(具有更多分组等)运行相同的 XSLT:

<?xml version="1.0" encoding="utf-8"?>
<Rootnode>
  <Properties Attribute="xxx">
    <Type>1</Type>
    <Size>10</Size>
  </Properties>
  <Other>
    <blah>h</blah>
  </Other>
  <Other2>
    <blah>h</blah>
  </Other2>
  <Properties Attribute="yyy">
    <xType>5</xType>
    <xSize>10</xSize>
  </Properties>
  <Items>
    <Item4>8</Item4>
  </Items>
  <Items place="US">
    <Item9>8</Item9>
  </Items>
  <Items>
    <Item1>8</Item1>
  </Items>
  <Properties Attribute2="xxx">
    <zType>1</zType>
    <zSize>10</zSize>
  </Properties>
  <Properties Attribute="xxx">
    <elephantType>5</elephantType>
    <elephantSize>15</elephantSize>
  </Properties>
  <Items place="UK">
    <Item1>8</Item1>
  </Items>
</Rootnode>

...再次,我认为正确的答案是:

<?xml version="1.0"?>
<Rootnode>
  <Properties Attribute="xxx">
    <Size>10</Size>
    <Type>1</Type>
    <elephantSize>15</elephantSize>
    <elephantType>5</elephantType>
  </Properties>
  <Properties Attribute="yyy">
    <xSize>10</xSize>
    <xType>5</xType>
  </Properties>
  <Properties Attribute2="xxx">
    <zSize>10</zSize>
    <zType>1</zType>
  </Properties>
  <Items>
    <Item1>8</Item1>
    <Item4>8</Item4>
  </Items>
  <Items place="UK">
    <Item1>8</Item1>
  </Items>
  <Items place="US">
    <Item9>8</Item9>
  </Items>
</Rootnode>

假设:

  • 我假设每个<Properties>and<Items>元素只有一个属性,它应该是分组确定器。
  • 如果以上不正确,至少,我假设该元素的第一个属性应该是分组确定器。

解释:

  1. 因为这是一个 XSLT 1.0 解决方案,Muenchian Grouping所以在唯一选择器下对节点和属性进行分组时的顺序;因此,我们定义了两个键:一个用于<Properties>元素,一个用于<Items>元素。

  2. 第一个模板是Identity Transform- 它的工作是将源文档中的所有节点和属性按原样输出到结果文档。

  3. 第二个模板匹配<Rootnode>元素。指示仅将模板应用于最先出现在其各自键中的那些<Properties>和元素;<Items>这具有仅处理唯一元素的预期效果(基于它们的第一个属性的名称和值)。

    指定元素时<xsl:apply-templates>,请注意,在这两种情况下,都指示按照相同的属性名称/值对对结果进行排序。

    请注意,每个<xsl:apply-templates>元素都有一个参数(通过<xsl:with-param>)。正如您将看到的,处理<Properties><Items>元素的代码几乎相同。唯一的区别是我们从中获取结果的关键。因此,我选择将该逻辑整合到第三个模板中,并通过此参数考虑可变性。

  4. 第三个模板同时匹配<Properties><Items>元素。对于每一个,原始节点都被复制(就像它的属性一样)。最后,将模板应用于该元素的所有子元素(进行适当的排序[这一次,基于子元素本身的名称])。

于 2012-11-12T20:29:41.030 回答
1

如果您已经拥有了一些东西而不是一无所有,那么您将更有可能获得帮助。首先,创建一个模板来匹配 Properties 和 Items ( match="Properties | Items"),其内容只是复制匹配的元素:<xsl:copy-of select="." />

这会给你一些工作代码来展示。

我建议的下一步是发布所需输出的示例,以及 XSLT 代码给出的实际输出。

这将为人们在回答您的问题时提供一个更小的差距。

于 2012-11-12T16:22:50.247 回答