使用XSLT 2.0进行XML重组

时间:2019-01-11 14:13:33

标签: xml xslt-2.0

我正在尝试重组xml。因此需要拆分产品。我已经在自己的帮助下完成了一些xslt,但是这些都是用于将XML拆分为多个XML的。但是,这似乎更具挑战性。我在努力从哪里开始。任何帮助都会很棒。我正在使用XSLT 2.0。

欢呼

输入XML


    <div property="title">
        {% if content.title %}
            <h1>{{ content.title }}</h1>
        {% endif %}
    </div>

结果XML

<?xml version="1.0"?>
<Order_Root>
  <Orders Number="12345">
    <Info Name="John Doe" Reference="1/2/2019">
      <LineItems>
        <LineItem LineItemNumber="01" CustomerProductName="Test">
          <LineItemPrice Price="0" Charge="0" />
          <Products>
            <Product ProductName="A" />
            <Product ProductName="B" />
            <Product ProductName="C" />
          </Products>
        </LineItem>
      </LineItems>
    </Info>
  </Orders>
</Order_Root>

1 个答案:

答案 0 :(得分:0)

我认为它可以作为将XSLT 3的snapshot函数与第二种模式和隧道参数一起用于传递该LineItemPrice的一个很好的例子:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:mode name="price" on-no-match="shallow-copy"/>

    <xsl:template match="LineItem">
        <xsl:apply-templates select=".//Product!snapshot()/ancestor::LineItem" mode="price">
            <xsl:with-param name="price" tunnel="yes" select="LineItemPrice"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="LineItem" mode="price">
        <xsl:param name="price" tunnel="yes"/>
        <xsl:copy>
            <xsl:apply-templates select="@*, $price, node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFN1y8J

XSLT 3随Saxon 9.8或更高版本或Altova 2017及更高版本一起提供,因此,如果您使用最新的XSLT 2处理器,则您的处理器也可以使用XSLT 3代替标记的XSLT 2。

XSLT 2没有snapshot,但是您当然可以尝试采用相同的方法,将每种产品推入不同的模式以在那里重构子树,现在只需要排除其他模板除Product以外的所有内容:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="2.0">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

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

    <xsl:template match="LineItem">
        <xsl:apply-templates select=".//Product"/>
    </xsl:template>

    <xsl:template match="Product">
        <xsl:apply-templates select="ancestor::LineItem" mode="price">
            <xsl:with-param name="product" tunnel="yes" select="."/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="Product" mode="price">
        <xsl:param name="product" tunnel="yes"/>
        <xsl:if test=". is $product">
            <xsl:next-match/>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFN1y8J/1