使用 xslt 从 xml 中提取唯一组

发布于 2024-09-14 17:38:58 字数 1061 浏览 8 评论 0原文

我意识到您不能在 xsl 中使用数组,并且通常执行下面的任务需要一个数组。这就是我需要的...

示例 xml 代码...

<products>
 <product>
  <productNumber>1</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>2</productNumber>
  <productType>TypeB</productType>
 </product>
 <product>
  <productNumber>3</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>4</productNumber>
  <productType>TypeC</productType>
 </product>
 <product>
  <productNumber>5</productNumber>
  <productType>TypeA</productType>
 </product>
</products>

上面是唯一“产品”的列表,每个产品都分配有一个“productType”,可以在整个 xml 中重复多次。我希望 xsl 为每个“productType”提取一个条目而不重复。

上面的最终结果会是这样的......

TypeA
TypeB
TypeC

而不是......

TypeA
TypeB
TypeA
TypeC
TypeA

我不能是唯一一个寻找这种功能的人。

想法?

I realize you can't use arrays in xsl and normally to do the task below it would take an array. Here's what I need...

Sample xml code...

<products>
 <product>
  <productNumber>1</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>2</productNumber>
  <productType>TypeB</productType>
 </product>
 <product>
  <productNumber>3</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>4</productNumber>
  <productType>TypeC</productType>
 </product>
 <product>
  <productNumber>5</productNumber>
  <productType>TypeA</productType>
 </product>
</products>

Above is a listing of unique "products" and each product is assigned a "productType" that could be repeated several times throughout the xml. I would like the xsl to pull a single entry for each "productType" without repeats.

The end result of above would be something like...

TypeA
TypeB
TypeC

And not ....

TypeA
TypeB
TypeA
TypeC
TypeA

I can't be the only one that has looked for this kind of functionality.

thoughts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情栀口红 2024-09-21 17:38:58

此转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kProdByType"
      match="product" use="productType"/>

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

 <xsl:template match="/products">
  <products>
    <xsl:apply-templates select=
     "product[generate-id()
             =
             generate-id(key('kProdByType', productType)[1])
             ]
     "/>
  </products>
 </xsl:template>

 <xsl:template match="product">
   <productType value="{productType}">
    <xsl:apply-templates mode="copy"
     select="key('kProdByType', productType)"/>
   </productType>
 </xsl:template>

 <xsl:template match="product" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

当应用于提供的 XML 文档时:

<products>
 <product>
  <productNumber>1</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>2</productNumber>
  <productType>TypeB</productType>
 </product>
 <product>
  <productNumber>3</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>4</productNumber>
  <productType>TypeC</productType>
 </product>
 <product>
  <productNumber>5</productNumber>
  <productType>TypeA</productType>
 </product>
</products>

生成所需的正确分组

<products>
    <productType value="TypeA">
        <product>
            <productNumber>1</productNumber>
            <productType>TypeA</productType>
        </product>
        <product>
            <productNumber>3</productNumber>
            <productType>TypeA</productType>
        </product>
        <product>
            <productNumber>5</productNumber>
            <productType>TypeA</productType>
        </product>
    </productType>
    <productType value="TypeB">
        <product>
            <productNumber>2</productNumber>
            <productType>TypeB</productType>
        </product>
    </productType>
    <productType value="TypeC">
        <product>
            <productNumber>4</productNumber>
            <productType>TypeC</productType>
        </product>
    </productType>
</products>

请注意:是著名的 Muenchian 分组方法 的一个示例,它是 XSLT 1.0 中最快的已知分组技术。

XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/products">
   <xsl:for-each-group select="product"
        group-by="productType">
     <productType value="{productType}">
      <xsl:apply-templates select="current-group()"/>
     </productType>
   </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

当将此 XSLT 2.0 转换应用于所提供的 XML 文档时,会生成完全相同的、正确分组的结果

This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kProdByType"
      match="product" use="productType"/>

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

 <xsl:template match="/products">
  <products>
    <xsl:apply-templates select=
     "product[generate-id()
             =
             generate-id(key('kProdByType', productType)[1])
             ]
     "/>
  </products>
 </xsl:template>

 <xsl:template match="product">
   <productType value="{productType}">
    <xsl:apply-templates mode="copy"
     select="key('kProdByType', productType)"/>
   </productType>
 </xsl:template>

 <xsl:template match="product" mode="copy">
  <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<products>
 <product>
  <productNumber>1</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>2</productNumber>
  <productType>TypeB</productType>
 </product>
 <product>
  <productNumber>3</productNumber>
  <productType>TypeA</productType>
 </product>
 <product>
  <productNumber>4</productNumber>
  <productType>TypeC</productType>
 </product>
 <product>
  <productNumber>5</productNumber>
  <productType>TypeA</productType>
 </product>
</products>

produces the wanted, correct grouping:

<products>
    <productType value="TypeA">
        <product>
            <productNumber>1</productNumber>
            <productType>TypeA</productType>
        </product>
        <product>
            <productNumber>3</productNumber>
            <productType>TypeA</productType>
        </product>
        <product>
            <productNumber>5</productNumber>
            <productType>TypeA</productType>
        </product>
    </productType>
    <productType value="TypeB">
        <product>
            <productNumber>2</productNumber>
            <productType>TypeB</productType>
        </product>
    </productType>
    <productType value="TypeC">
        <product>
            <productNumber>4</productNumber>
            <productType>TypeC</productType>
        </product>
    </productType>
</products>

Do note: This is an example of the well-known Muenchian method for grouping, which is the fastest known gouping technique in XSLT 1.0.

XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/products">
   <xsl:for-each-group select="product"
        group-by="productType">
     <productType value="{productType}">
      <xsl:apply-templates select="current-group()"/>
     </productType>
   </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

when this XSLT 2.0 transformation is applied on the provided XML document, exactly the same, correctly-grouped result is produced.

恋你朝朝暮暮 2024-09-21 17:38:58

Dimitre 让我走上了正确的道路。这是我想出的适合我的需求的代码,一个简单的分隔输出流来支持 AJAX 调用...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:key name="kProdByBrand" match="Products/Product" use="Brand"/>

 <xsl:template match="Products">
   <xsl:for-each 
     select="Product
     [generate-id() = generate-id(key('kProdByBrand', Brand)[1])]"><xsl:sort
     select="Brand" /><xsl:value-of select="Brand" />|</xsl:for-each>
 </xsl:template>

</xsl:stylesheet>

给定一个 xml,它有很多看起来像这样的成员...

<Product>
    <Brand>Brand</Brand>
    <OldPN>myCompany Part Number</OldPN>    
            ...
</Product>

输出看起来像这样...

Brand|Brand1|Brand2|Brand3|

Dimitre got me going on the right path. Here is the code that I came up with that worked for my needs, a simple deliniated stream of output to support an AJAX call...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:key name="kProdByBrand" match="Products/Product" use="Brand"/>

 <xsl:template match="Products">
   <xsl:for-each 
     select="Product
     [generate-id() = generate-id(key('kProdByBrand', Brand)[1])]"><xsl:sort
     select="Brand" /><xsl:value-of select="Brand" />|</xsl:for-each>
 </xsl:template>

</xsl:stylesheet>

Given an xml that has many many members that look something like this...

<Product>
    <Brand>Brand</Brand>
    <OldPN>myCompany Part Number</OldPN>    
            ...
</Product>

The output looks like this...

Brand|Brand1|Brand2|Brand3|
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文