简体   繁体   English

XSLT从以下类型的XML结构中除去除某些节点以外的所有节点

[英]XSLT to remove all but certain nodes from the following type of XML structure

<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>

Now what I want is to ONLY include the Properties and Items. 现在,我只想包含属性和项目。 Preferably to join the Properties and Items groups together if the Attributes are the same name and value and to SORT both Properties and Items based on the Attributes and to sort the child nodes of both alphabetically. 优选地,如果属性是相同的名称和值,则将属性和项目组连接在一起,并基于属性对属性和项目进行排序,并按字母顺序对两个子节点进行排序。 So far I've reached a blank ;( 到目前为止,我还是一片空白;(

Required output is pretty much as ABach has shown. 所需的输出几乎与ABach所示的一样。 Although one thing I forgot to mention is that there could be other attributes on each Properties or Items and that I know the name of the Attribute I wish to sort on. 尽管我忘了提到的一件事是,每个“属性”或“项目”上可能还有其他属性,并且我知道我希望排序的属性的名称。 That I can amend easily enough. 我可以很容易地修改。

ie, required output 即所需的输出

<?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>

And apologies for lack of my efforts so far...I ended up in a right mess and didn't think it would help much...I'm pretty new to this stuff :) 很抱歉,到目前为止我没有付出很多努力。。。我陷入了混乱,认为并没有多大帮助。。。

As already pointed out by @LarsH, by not showing us the expected output XML, we're left to guess at what you really want. 正如@LarsH所指出的那样,通过不向我们显示期望的输出XML,我们可以猜测您真正想要的是什么。 That said, here's my attempt at an XSLT 1.0 solution. 就是说,这是我对XSLT 1.0解决方案的尝试。

When this XSLT: 当此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>

...the run against the provided XML: ...针对提供的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>

...what I guess is the correct output XML is produced: ...我猜是生成了正确的输出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>

Note that if this same XSLT is run against a slightly modified XML document (that has more groupings, etc.): 请注意,如果对稍有修改的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>

...again, what I assume is the correct answer is produced: ...再一次,我认为是正确的答案产生了:

<?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>

Assumptions: 假设:

  • I assume that each <Properties> and <Items> element has only one attribute and that it should be the grouping determiner. 我假设每个<Properties><Items>元素都只有一个属性,并且它应该是分组确定器。
  • If the above is not true, at the very least, I assume that the first attribute of that element should be the grouping determiner. 如果以上情况都不成立,那么我至少认为该元素的第一个属性应该是分组确定器。

Explanation: 说明:

  1. Because this is an XSLT 1.0 solution, Muenchian Grouping is the order of the day when grouping nodes and attributes under unique selectors; 因为这是XSLT 1.0解决方案, Muenchian Grouping是在唯一选择器下对节点和属性进行分组时的日常工作。 therefore, we define two keys: one for <Properties> elements and one for <Items> elements. 因此,我们定义了两个键:一个用于<Properties>元素,另一个用于<Items>元素。

  2. The first template is the Identity Transform - its job is to output all nodes and attributes from the source document to the result document as-is. 第一个模板是Identity Transform -其工作是将所有文档从源文档按原样输出到结果文档。

  3. The second template matches the <Rootnode> element. 第二个模板与<Rootnode>元素匹配。 It is instructed to apply templates to only those <Properties> and <Items> elements who are the first to appear in their respective keys; 指示仅将模板应用于首先出现在各自键中的那些<Properties><Items>元素。 this has the intended effect of only processing unique elements (based upon the name and value of their first attribute). 这具有仅处理唯一元素的预期效果(基于它们的第一个属性的名称和值)。

    When the <xsl:apply-templates> element is specified, note that in both instances, it is instructed to sort the results by that same attribute name/value pairing. 指定<xsl:apply-templates>元素后,请注意,在两种情况下,都将指示该属性按相同的属性名称/值对对结果进行排序。

    Do note that each <xsl:apply-templates> element is given a parameter (via <xsl:with-param> ). 请注意,每个<xsl:apply-templates>元素都有一个参数(通过<xsl:with-param> )。 As you'll see, the code to process both <Properties> and <Items> elements is nearly identical; 正如您将看到的,用于处理<Properties><Items>元素的代码几乎是相同的。 the only difference is the key that we grab results from. 唯一的区别是我们从中获取结果的关键。 Because of this, I chose to consolidate that logic into the third template and account for variability via this parameter. 因此,我选择将该逻辑合并到第三个模板中,并通过此参数说明可变性。

  4. The third template matches both <Properties> and <Items> elements. 第三个模板匹配<Properties><Items>元素。 For each, the original node is copied (as are its attributes). 对于每个节点,将复制原始节点(及其属性)。 Finally, templates are applied against all child elements of this element (with appropriate sorting occuring [this time, based on the name of the child element itself]). 最后,将模板应用于此元素的所有子元素([此时,基于子元素本身的名称]进行了适当的排序)。

You will be more likely to receive help if you already have something rather than nothing. 如果您已经有了东西而不是一无所有,那么您将更有可能获得帮助。 To get started, create a template that matches Properties and Items ( match="Properties | Items" ) whose content just copies the matched element: <xsl:copy-of select="." /> 首先,创建一个与Properties和Items相匹配的模板( match="Properties | Items" ),其内容只是复制匹配的元素: <xsl:copy-of select="." /> <xsl:copy-of select="." /> . <xsl:copy-of select="." />

That will give you some working code to show. 这将为您显示一些工作代码。

The next step I would suggest is posting a sample of the desired output, and the actual output given by your XSLT code. 我建议的下一步是发布所需输出的样本,以及XSLT代码给出的实际输出。

That will provide a much smaller gap for people to bridge in answering your question. 这将使人们在回答您的问题时弥合的差距大大缩小。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM