如何按顺序 运行 这些 XSL 模板

How to run these XSL templates in sequence

作为序言,我最近才了解我们可以使用 XSL 做的更多高级事情。

我目前正在尝试转换 XML 文件中提供的数据,然后将其输出转换为 JSON 文件。

我可以单独完成这些事情中的每一个(使用我在网上找到的 JSON 的 XSL)并且我已经尝试 运行 使用 apply-templates、call-template、mode= "run2" 等等,无法让他们表现出来。我只能得到其中之一。

我使用的 XSL 是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   version="1.0">
  <xsl:output method="text" encoding="utf-8"/>

<!-- Extract required information-->
  <xsl:template match="/" name="xmlOutput">
    <jobDetails>
      <orderId>
        <xsl:value-of select="/Order/OrderId"/>
      </orderId>
      <xsl:variable name="jobId" select="/Order/OrderLines/OrderLine/OrderLineId" />
      <orderLine>
        <xsl:value-of select="substring-after($jobId,'d')"/>
      </orderLine>
      <xsl:for-each select="/Order/OrderLines/OrderLine">
        <name>
          <xsl:value-of select="ProductName"/>
        </name>
        <copies>
          <xsl:value-of select="Quantity"/>
        </copies>
        <url>
          <xsl:value-of select="AssetUrl"/>
        </url>
        <nestQueueName>smile_test</nestQueueName>
        <customer_info>
          <first_name>
            <xsl:value-of select="/Order/Customer/FirstName"/>
          </first_name>
          <last_name>
            <xsl:value-of select="/Order/Customer/LastName"/>
          </last_name>
          <street1>
            <xsl:value-of select="/Order/ShippingAddress/Address1"/>
          </street1>
          <street2>
            <xsl:value-of select="/Order/ShippingAddress/Address2"/>
          </street2>
          <city>
            <xsl:value-of select="/Order/ShippingAddress/Town"/>
          </city>
          <state>
            <xsl:value-of select="/Order/ShippingAddress/State"/>
          </state>
          <country>
            <xsl:value-of select="/Order/ShippingAddress/Country"/>
          </country>
          <phone>
            <xsl:value-of select="/Order/ShippingAddress/Phone"/>
          </phone>
          <email>
            <xsl:value-of select="/Order/ShippingAddress/Email"/>
          </email>

        </customer_info>
      </xsl:for-each>
    </jobDetails>
  </xsl:template>

<!--Convert XML to JSON-->
  <xsl:template match="/">
    <xsl:variable name="xmlOutputVar">
      <xsl:apply-templates select="/"/>
    </xsl:variable>

    <xsl:apply-templates select="$xmlOutputVar"/>
  </xsl:template>

  <!-- Object or Element Property-->
  <xsl:template match="*">
        "    <xsl:value-of select="name()"/>
" :    <xsl:call-template name="Properties"/>
  </xsl:template>

  <!-- Array Element -->
  <xsl:template match="*" mode="ArrayElement">
    <xsl:call-template name="Properties"/>
  </xsl:template>

  <!-- Object Properties -->
  <xsl:template name="Properties">
    <xsl:variable name="childName" select="name(*[1])"/>
    <xsl:choose>
      <xsl:when test="not(*|@*)">"        <xsl:value-of select="."/>
"</xsl:when>
      <xsl:when test="count(*[name()=$childName]) > 1">{ "        <xsl:value-of select="$childName"/>
" :[        <xsl:apply-templates select="*" mode="ArrayElement"/>
] }</xsl:when>
      <xsl:otherwise>{
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="*"/>
    }</xsl:otherwise>
    </xsl:choose>
    <xsl:if test="following-sibling::*">,</xsl:if>
  </xsl:template>

  <!-- Attribute Property -->
  <xsl:template match="@*">"    <xsl:value-of select="name()"/>
" : "    <xsl:value-of select="."/>
",
  </xsl:template>

</xsl:stylesheet>

这两个目前没有配置为 运行 一起,因为我已经将其剥离以简化,但管道应该是 Source XML -> 提取信息模板 ->转换为 JSON 个模板。

我知道这两个 template/template 集是有效的,因为我已经在源 XML 上单独尝试过它们(见下文),但是当我尝试 link 它们时,我无法获得正确的输出。

有人能帮忙吗?

来源XML:

<?xml version="1.0" encoding="utf-8"?>
<Order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <OrderId>1234</OrderId>
    <StoreFrontId>00</StoreFrontId>
    <StoreFrontName>Example Store</StoreFrontName>
    <Amount>0.0000</Amount>
    <Taxes>0.0000</Taxes>
    <TotalDiscount>0.0000</TotalDiscount>
    <OrderStatusId>1</OrderStatusId>
    <OrderStatus>Confirmed</OrderStatus>
    <PaymentStatusId>2</PaymentStatusId>
    <PaymentStatus>Paid</PaymentStatus>
    <ShippingStatusId>1</ShippingStatusId>
    <ShippingStatus>Pending</ShippingStatus>
    <OrderDiscount>0.0000</OrderDiscount>
    <SubTotalDiscountInclTax>0.0000</SubTotalDiscountInclTax>
    <SubTotalDiscountExclTax>0.0000</SubTotalDiscountExclTax>
    <ShippingTax>0.0000</ShippingTax>
    <ShippingPrice>0.0000</ShippingPrice>
    <ShippingMethod>Test</ShippingMethod>
    <ShippingMethodSystemName>Test</ShippingMethodSystemName>
    <ShippingMethodCode>24</ShippingMethodCode>
    <PaymentMethod>Payments.PurchaseOrder</PaymentMethod>
    <VatNumber />
    <OrderWeight>1.0000</OrderWeight>
    <Currency>GBP</Currency>
    <PurchaseOrderNumber />
    <Customer>
        <CatfishId>50242</CatfishId>
        <ExternalId>External ID</ExternalId>
        <Email>test@email.com</Email>
        <FirstName>TestFirst</FirstName>
        <LastName>TestLast</LastName>
        <PhoneNumber>01234567890</PhoneNumber>
        <CompanyName>CompanyName</CompanyName>
        <AddressLine1>AddressLine1</AddressLine1>
        <AddressLine2>AddressLine2</AddressLine2>
        <Town>Town</Town>
        <County>County</County>
        <Country>United Kingdom</Country>
        <CountryCode>GB</CountryCode>
        <ZipPostalCode>AB01 1AB</ZipPostalCode>
    </Customer>
    <OrderNotes />
    <OrderDateUtc>2018-07-27</OrderDateUtc>
    <DispatchBy>2018-07-27</DispatchBy>
    <BillingAddress>
        <ExternalId />
        <FirstName>Billing</FirstName>
        <LastName>Address</LastName>
        <Address1>BALO</Address1>
        <Postcode>BA73 5ST</Postcode>
        <State>Aberdeenshire</State>
        <Town>BAT</Town>
        <Country>United Kingdom</Country>
        <CountryCode>GB</CountryCode>
        <Email>test@email.com</Email>
        <CompanyName>BillingAddressCompany</CompanyName>
    </BillingAddress>
    <ShippingAddress>
        <ExternalId />
        <FirstName>Billing</FirstName>
        <LastName>Address</LastName>
        <Address1>BALO</Address1>
        <Postcode>BA73 5ST</Postcode>
        <State>Aberdeenshire</State>
        <Town>BAT</Town>
        <Country>United Kingdom</Country>
        <CountryCode>GB</CountryCode>
        <Email>test@email.com</Email>
        <CompanyName>BillingAddressCompany</CompanyName>
    </ShippingAddress>
    <OrderLines>
        <OrderLine>
            <OrderLineId>v2604</OrderLineId>
            <ProductExternalId>External ID</ProductExternalId>
            <ProductVariantExternalId>Variant External ID</ProductVariantExternalId>
            <Sku>0000</Sku>
            <ProductName>ProductName</ProductName>
            <Quantity>1</Quantity>
            <TotalPrice>0.0000</TotalPrice>
            <TotalTax>0.0000</TotalTax>
            <Weight>1.0000</Weight>
            <DiscountAmountInclTax>0.0000</DiscountAmountInclTax>
            <DiscountAmountExclTax>0.0000</DiscountAmountExclTax>
            <AssetUrl>urlGoesHere</AssetUrl>
            <PrintParameters />
            <ProductAttributes>
                <ProductAttribute>
                    <Name>Attribute1</Name>
                    <Value>A</Value>
                    <Values>
                        <ProductAttributeValue>
                            <Value>A</Value>
                        </ProductAttributeValue>
                    </Values>
                </ProductAttribute>
                <ProductAttribute>
                    <Name>Attribute2</Name>
                    <Value />
                    <Values>
                        <ProductAttributeValue>
                            <Value />
                        </ProductAttributeValue>
                    </Values>
                </ProductAttribute>
                <ProductAttribute>
                    <Name>Attribute3</Name>
                    <Value />
                    <Values>
                        <ProductAttributeValue>
                            <Value />
                        </ProductAttributeValue>
                    </Values>
                </ProductAttribute>
                <ProductAttribute>
                    <Name>Attribute4</Name>
                    <Value />
                    <Values>
                        <ProductAttributeValue>
                            <Value />
                        </ProductAttributeValue>
                    </Values>
                </ProductAttribute>
            </ProductAttributes>
            <Totals>
                <UnitPrice>0.00000000</UnitPrice>
                <TotalPrice>0.00000000</TotalPrice>
                <TotalTax>0.00000000</TotalTax>
                <DiscountAmountInclTax>0.00000000</DiscountAmountInclTax>
                <DiscountAmountExclTax>0.00000000</DiscountAmountExclTax>
            </Totals>
        </OrderLine>
    </OrderLines>
    <CheckoutAttributes />
    <Totals>
        <CurrencyCode>GBP</CurrencyCode>
        <TotalPrice>0.00000000</TotalPrice>
        <TotalDiscount>0</TotalDiscount>
        <OrderDiscount>0.00000000</OrderDiscount>
        <SubTotalDiscountInclTax>0.00000000</SubTotalDiscountInclTax>
        <SubTotalDiscountExclTax>0.00000000</SubTotalDiscountExclTax>
        <TotalTax>0.00000000</TotalTax>
        <ShippingPrice>0.00000000</ShippingPrice>
        <ShippingTax>0.00000000</ShippingTax>
    </Totals>
</Order>

P.S。我不可能 运行 在 XML 上使用两个单独的 XSL 文件,也不可能使用 XSL 1.0

以外的任何东西

编辑: 在听取评论中给出的建议后,我将 XSLT 修改为以下内容:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
   version="1.0">
  <xsl:output method="text" encoding="utf-8"/>

<!-- Extract required information-->
  <xsl:template match="/" name="xmlOutput">
    <jobDetails>
      <orderId>
        <xsl:value-of select="/Order/OrderId"/>
      </orderId>
      <xsl:variable name="jobId" select="/Order/OrderLines/OrderLine/OrderLineId" />
      <orderLine>
        <xsl:value-of select="substring-after($jobId,'d')"/>
      </orderLine>
      <xsl:for-each select="/Order/OrderLines/OrderLine">
        <name>
          <xsl:value-of select="ProductName"/>
        </name>
        <copies>
          <xsl:value-of select="Quantity"/>
        </copies>
        <url>
          <xsl:value-of select="AssetUrl"/>
        </url>
        <nestQueueName>smile_test</nestQueueName>
        <customer_info>
          <first_name>
            <xsl:value-of select="/Order/Customer/FirstName"/>
          </first_name>
          <last_name>
            <xsl:value-of select="/Order/Customer/LastName"/>
          </last_name>
          <street1>
            <xsl:value-of select="/Order/ShippingAddress/Address1"/>
          </street1>
          <street2>
            <xsl:value-of select="/Order/ShippingAddress/Address2"/>
          </street2>
          <city>
            <xsl:value-of select="/Order/ShippingAddress/Town"/>
          </city>
          <state>
            <xsl:value-of select="/Order/ShippingAddress/State"/>
          </state>
          <country>
            <xsl:value-of select="/Order/ShippingAddress/Country"/>
          </country>
          <phone>
            <xsl:value-of select="/Order/ShippingAddress/Phone"/>
          </phone>
          <email>
            <xsl:value-of select="/Order/ShippingAddress/Email"/>
          </email>

        </customer_info>
      </xsl:for-each>
    </jobDetails>
  </xsl:template>

<!--Convert XML to JSON-->
  <xsl:template match="/">
    <xsl:variable name="xmlOutputVar">
      <xsl:call-template name="xmlOutput"/>
    </xsl:variable>

    <xsl:apply-templates select="exsl:node-set($xmlOutputVar)/node()"/>
  </xsl:template>

  <!-- Object or Element Property-->
  <xsl:template match="*">
        "    <xsl:value-of select="name()"/>
" :    <xsl:call-template name="Properties"/>
  </xsl:template>

  <!-- Array Element -->
  <xsl:template match="*" mode="ArrayElement">
    <xsl:call-template name="Properties"/>
  </xsl:template>

  <!-- Object Properties -->
  <xsl:template name="Properties">
    <xsl:variable name="childName" select="name(*[1])"/>
    <xsl:choose>
      <xsl:when test="not(*|@*)">"        <xsl:value-of select="."/>
"</xsl:when>
      <xsl:when test="count(*[name()=$childName]) > 1">{ "        <xsl:value-of select="$childName"/>
" :[        <xsl:apply-templates select="*" mode="ArrayElement"/>
] }</xsl:when>
      <xsl:otherwise>{
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="*"/>
    }</xsl:otherwise>
    </xsl:choose>
    <xsl:if test="following-sibling::*">,</xsl:if>
  </xsl:template>

  <!-- Attribute Property -->
  <xsl:template match="@*">"    <xsl:value-of select="name()"/>
" : "    <xsl:value-of select="."/>
",
  </xsl:template>

</xsl:stylesheet>

但是如果我 运行 将两个转换作为单独的 XSL 文件,它会产生不同的输出。

如果我 运行 他们分开,我最终得到:

{

    "jobDetails" :{

    "orderId" :"1234",
    "orderLine" :"",
    "name" :"ProductName",
    "copies" :"1",
    "url" :"urlGoesHere",
    "nestQueueName" :"smile_test",
    "customer_info" :{

    "first_name" :"TestFirst",
    "last_name" :"TestLast",
    "street1" :"BALO",
    "street2" :"",
    "city" :"BAT",
    "state" :"Aberdeenshire",
    "country" :"United Kingdom",
    "phone" :"",
    "email" :"test@email.com"
            }
            }}

但是,如果我 运行 它们在同一个 XSL 文件中,我最终会得到:


        "    jobDetails
" :    {

        "    orderId
" :    "        1234
",
        "    orderLine
" :    "        
",
        "    name
" :    "        ProductName
",
        "    copies
" :    "        1
",
        "    url
" :    "        urlGoesHere
",
        "    nestQueueName
" :    "        smile_test
",
        "    customer_info
" :    {

        "    first_name
" :    "        TestFirst
",
        "    last_name
" :    "        TestLast
",
        "    street1
" :    "        BALO
",
        "    street2
" :    "        
",
        "    city
" :    "        BAT
",
        "    state
" :    "        Aberdeenshire
",
        "    country
" :    "        United Kingdom
",
        "    phone
" :    "        
",
        "    email
" :    "        test@email.com
"
    }
    }

我看不出是什么导致了不同的输出,有人可以帮忙吗?

改变

<xsl:variable name="xmlOutputVar">
  <xsl:apply-templates select="/"/>
</xsl:variable>

<xsl:variable name="xmlOutputVar">
  <xsl:call-template name="xmlOutput"/>
</xsl:variable>

然后使用支持的扩展功能,例如exsl:node-set 并替换

<xsl:apply-templates select="$xmlOutputVar"/>

<xsl:apply-templates select="exsl:node-set($xmlOutputVar)/node()" xmlns:exsl="http://exslt.org/common"/>