XSLT 1.0 转换 - 将同级数据移动到特定同级数据

发布于 2024-12-25 07:25:58 字数 3135 浏览 5 评论 0原文

我在进行 xslt 转换时遇到困难,我非常感谢一些帮助。我花了相当多的时间使用 XPath 和 XQuery 中的各种方法。另外,我仅限于 xslt 1.0。

该转换涉及对 xml 订单文件中的产品项目进行更改。原始 XML 文件包含项目,但某些行项目是折扣优惠券参考(请参阅下面的 dsc-102 和 dsc-133)。我需要实现的是删除折扣优惠券引用的“orderDetails”节点,并将包含的信息添加到其相应的同级产品项目中(请参阅下面的转换后的 XML 示例)。每个折扣优惠券参考在其产品名称末尾指定其相应的产品项目(例如….[glv-001][glv-003])。

原始 XML 文件 - 以下是原始 XML 文件,其中包含 1 个订单、3 个产品项目和 2 个折扣优惠券参考。折扣参考“dsc-102”对应于 2 个产品项目“glv-001”和“glv-003”。折扣参考“dsc-133”对应于 1 个产品项目“sho-123”。

<xmldata>
<Order>
    <orderID>1010</orderID>
    <custFirstName>Jim</custFirstName>
    <custLastName>Jones</custLastName>
    <orderDetails>
        <productCode>sho-123</productCode>
        <productName>Leather Windsor Shoes - size 10</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-001</productCode>
        <productName>Leather gloves - size Small</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-003</productCode>
        <productName>Leather gloves - size XLarge</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-102</productCode>
        <productName>10% Discount for Leather Gloves [glv-001][glv-003]</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-133</productCode>
        <productName>Free Shipping for Windsor Shoes [sho-123]</productName>
    </orderDetails>
</Order>

转换后的 XML 文件 - 下面是我想要实现的转换后的 XML。转移已删除两个折扣优惠券引用,并向其相应的同级产品项目添加“discountCoupon”节点。

<xmldata>
<Orders>
    <orderID>1010</orderID>
    <custFirstName>Jim</custFirstName>
    <custLastName>Jones</custLastName>
    <orderDetails>
        <productCode>sho-123</productCode>
        <productName>Leather Windsor Shoes - size 10</productName>
        <discountCoupon>Free Shipping for Windsor Shoes</discountCoupon>
    </orderDetails>
    <orderDetails>
        <productCode>glv-001</productCode>
        <productName>Leather gloves - size Small</productName>
        <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
    </orderDetails>
    <orderDetails>
        <productCode>glv-003</productCode>
        <productName>Leather gloves - size XLarge</productName>
        <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
    </orderDetails>
</Orders>

到目前为止我已经尝试过的 - 老实说,我在这个问题上取得的成功非常有限。我最接近的是以下内容。然而,这与我的预期结果相去甚远,并且“匹配”是 XLST 2.0 函数,而我仅限于版本 1。

<xsl:if test="../OrderDetails[ProductCode = 'DSC-15'] and matches(ProductCode,'AH010585059',i)">DiscountCoupon</xsl:if>

如果有人可以帮我解决这个问题,或者推动我朝正确的方向前进,我将非常感激它。

-干杯。

I am having trouble working out an xslt transformation that I would really appreciate some help with it. I have spent quite a bit of time using a variety of methods in XPath and XQuery. Also, I am restricted to xslt 1.0.

The transformation involves making changes to product items in an xml order file. The original XML file has Items however some of the line Items are discount coupon references (see dsc-102 and dsc-133 below). What I need to achieve is to remove the 'orderDetails' nodes for discount coupon references and add the containing information to their corresponding sibling product items (see the Transformed XML sample below). Each discount coupon reference specifies its corresponding product items at the end of its product name (eg ….[glv-001][glv-003]).

Original XML File -
Below is the original XML file that contains 1 order with 3 product items and 2 discount coupon references. The discount reference 'dsc-102' corresponds to 2 product items 'glv-001' and 'glv-003'. The discount reference 'dsc-133' corresponds to 1 product item 'sho-123'.

<xmldata>
<Order>
    <orderID>1010</orderID>
    <custFirstName>Jim</custFirstName>
    <custLastName>Jones</custLastName>
    <orderDetails>
        <productCode>sho-123</productCode>
        <productName>Leather Windsor Shoes - size 10</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-001</productCode>
        <productName>Leather gloves - size Small</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-003</productCode>
        <productName>Leather gloves - size XLarge</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-102</productCode>
        <productName>10% Discount for Leather Gloves [glv-001][glv-003]</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-133</productCode>
        <productName>Free Shipping for Windsor Shoes [sho-123]</productName>
    </orderDetails>
</Order>

Transformed XML File -
Below is the transformed XML that I want to achieve. The transfer has removed both discount coupon references and added a 'discountCoupon' node to their corresponding sibling product items.

<xmldata>
<Orders>
    <orderID>1010</orderID>
    <custFirstName>Jim</custFirstName>
    <custLastName>Jones</custLastName>
    <orderDetails>
        <productCode>sho-123</productCode>
        <productName>Leather Windsor Shoes - size 10</productName>
        <discountCoupon>Free Shipping for Windsor Shoes</discountCoupon>
    </orderDetails>
    <orderDetails>
        <productCode>glv-001</productCode>
        <productName>Leather gloves - size Small</productName>
        <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
    </orderDetails>
    <orderDetails>
        <productCode>glv-003</productCode>
        <productName>Leather gloves - size XLarge</productName>
        <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
    </orderDetails>
</Orders>

What I have Tried So far -
To be totally honest I have had quite limited success with this problem. The closest I have got with it has been with the following. However, it was pretty far off my intended result and 'matches' is a XLST 2.0 function and I am restricted to version 1.

<xsl:if test="../OrderDetails[ProductCode = 'DSC-15'] and matches(ProductCode,'AH010585059',i)">DiscountCoupon</xsl:if>

If someone could give me a hand with this problem or give me a push in the right direction I would really appreciate it.

-Cheers.

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

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

发布评论

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

评论(2

白首有我共你 2025-01-01 07:25:58

与@lwburk类似的解决方案,但更简单 - 没有并且没有

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

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

 <xsl:template match=
  "orderDetails[not(starts-with(productCode, 'dsc-'))]">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
   <xsl:apply-templates mode="coupon" select=
   "../orderDetails[starts-with(productCode, 'dsc-')]
                    [contains(productName,
                           concat('[', current()/productCode, ']')
                          )
                     ]/productName
   "/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="orderDetails[starts-with(productCode, 'dsc-')]"/>

 <xsl:template match="productName" mode="coupon">
  <discountCoupon>
   <xsl:value-of select="substring-before(., ' [')"/>
  </discountCoupon>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<Order>
    <orderID>1010</orderID>
    <custFirstName>Jim</custFirstName>
    <custLastName>Jones</custLastName>
    <orderDetails>
        <productCode>sho-123</productCode>
        <productName>Leather Windsor Shoes - size 10</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-001</productCode>
        <productName>Leather gloves - size Small</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-003</productCode>
        <productName>Leather gloves - size XLarge</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-102</productCode>
        <productName>10% Discount for Leather Gloves [glv-001][glv-003]</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-133</productCode>
        <productName>Free Shipping for Windsor Shoes [sho-123]</productName>
    </orderDetails>
</Order>

生成所需的正确结果

<Order>
   <orderID>1010</orderID>
   <custFirstName>Jim</custFirstName>
   <custLastName>Jones</custLastName>
   <orderDetails>
      <productCode>sho-123</productCode>
      <productName>Leather Windsor Shoes - size 10</productName>
      <discountCoupon>Free Shipping for Windsor Shoes</discountCoupon>
   </orderDetails>
   <orderDetails>
      <productCode>glv-001</productCode>
      <productName>Leather gloves - size Small</productName>
      <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
   </orderDetails>
   <orderDetails>
      <productCode>glv-003</productCode>
      <productName>Leather gloves - size XLarge</productName>
      <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
   </orderDetails>
</Order>

说明:正确使用和覆盖 ><一个href="http://dpawson.co.uk/xsl/sect2/identity.html" rel="nofollow">身份规则和模板/模式匹配。

A solution similar to that of @lwburk, but simpler -- no <xsl:if> and no <xsl:variable>:

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

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

 <xsl:template match=
  "orderDetails[not(starts-with(productCode, 'dsc-'))]">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
   <xsl:apply-templates mode="coupon" select=
   "../orderDetails[starts-with(productCode, 'dsc-')]
                    [contains(productName,
                           concat('[', current()/productCode, ']')
                          )
                     ]/productName
   "/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="orderDetails[starts-with(productCode, 'dsc-')]"/>

 <xsl:template match="productName" mode="coupon">
  <discountCoupon>
   <xsl:value-of select="substring-before(., ' [')"/>
  </discountCoupon>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document:

<Order>
    <orderID>1010</orderID>
    <custFirstName>Jim</custFirstName>
    <custLastName>Jones</custLastName>
    <orderDetails>
        <productCode>sho-123</productCode>
        <productName>Leather Windsor Shoes - size 10</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-001</productCode>
        <productName>Leather gloves - size Small</productName>
    </orderDetails>
    <orderDetails>
        <productCode>glv-003</productCode>
        <productName>Leather gloves - size XLarge</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-102</productCode>
        <productName>10% Discount for Leather Gloves [glv-001][glv-003]</productName>
    </orderDetails>
    <orderDetails>
        <productCode>dsc-133</productCode>
        <productName>Free Shipping for Windsor Shoes [sho-123]</productName>
    </orderDetails>
</Order>

the wanted, correct result is produced:

<Order>
   <orderID>1010</orderID>
   <custFirstName>Jim</custFirstName>
   <custLastName>Jones</custLastName>
   <orderDetails>
      <productCode>sho-123</productCode>
      <productName>Leather Windsor Shoes - size 10</productName>
      <discountCoupon>Free Shipping for Windsor Shoes</discountCoupon>
   </orderDetails>
   <orderDetails>
      <productCode>glv-001</productCode>
      <productName>Leather gloves - size Small</productName>
      <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
   </orderDetails>
   <orderDetails>
      <productCode>glv-003</productCode>
      <productName>Leather gloves - size XLarge</productName>
      <discountCoupon>10% Discount for Leather Gloves</discountCoupon>
   </orderDetails>
</Order>

Explanation: Appropriate use and overriding of the identity rule, and templates/pattern-matching.

夜空下最亮的亮点 2025-01-01 07:25:58

以下样式表产生正确的结果:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="orderDetails[not(starts-with(productCode, 'dsc'))]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <xsl:variable name="discount"
                select="../orderDetails[starts-with(productCode, 'dsc') and 
                      contains(productName, 
                         concat('[', current()/productCode, ']'))]/productName"/>
            <xsl:if test="$discount">
                <discountCoupon>
                    <xsl:value-of select="substring-before($discount, ' [')"/>
                </discountCoupon>
            </xsl:if>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="orderDetails[starts-with(productCode, 'dsc')]"/>
</xsl:stylesheet>

注释和解释:

  • 身份转换通过未更改的方式复制大多数节点
  • 折扣在处理时被复制到非折扣元素中
  • 折扣 orderDetails 是被忽略

The following stylesheet produces the correct result:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="orderDetails[not(starts-with(productCode, 'dsc'))]">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
            <xsl:variable name="discount"
                select="../orderDetails[starts-with(productCode, 'dsc') and 
                      contains(productName, 
                         concat('[', current()/productCode, ']'))]/productName"/>
            <xsl:if test="$discount">
                <discountCoupon>
                    <xsl:value-of select="substring-before($discount, ' [')"/>
                </discountCoupon>
            </xsl:if>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="orderDetails[starts-with(productCode, 'dsc')]"/>
</xsl:stylesheet>

Notes and explanation:

  • The identity transform copies most nodes through unchanged
  • Discounts are copied into non-discount elements as they're processed
  • Discount orderDetails are ignored
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文