连接来自不同节点的数据并使用xslt以有序方式显示它们

时间:2012-01-12 19:51:59

标签: xml xslt text

连接来自不同表的数据并使用xslt以有序方式显示它们: 我有关于客户和产品的信息。 1客户可以使用许多产品。 (1:n关系) Similary 1产品被许多客户消费。 (1:N)

当我处理消费者节点信息时,我需要获取产品信息并以tabluar / csv格式显示它。

在处理Products节点信息时,我需要获取客户信息并以tabluar / csv格式显示。

输入如下。

<?xml version='1.0' encoding='ISO-8859-1' ?>
<info>
<Customers>
    <Customer>
     <CustomerName>01NAME</CustomerName>
     <CustomerAddress>Address1</CustomerAddress>   
     <CustomerUsesProduct>
        <ProductUsed>
            <ProductNumber>PROD01</ProductNumber>
            <ProductNumber>PROD02</ProductNumber>        
        </ProductUsed>
        </CustomerUsesProduct>      
     <CustomerId>CUSTID01</CustomerId>      
    </Customer>

    <Customer>
     <CustomerName>02NAME</CustomerName>
     <CustomerAddress>Address2</CustomerAddress>   
     <CustomerUsesProduct>
        <ProductUsed>
            <ProductNumber>PROD01</ProductNumber>
        </ProductUsed>
        </CustomerUsesProduct>      
     <CustomerId>CUSTID02</CustomerId>      
    </Customer>

    <Customer>
     <CustomerName>03NAME</CustomerName>
     <CustomerAddress>Address3</CustomerAddress>   
     <CustomerUsesProduct>
        <ProductUsed>
            <ProductNumber>PROD03</ProductNumber>
        </ProductUsed>
        </CustomerUsesProduct>      
     <CustomerId>CUSTID03</CustomerId>
    </Customer>

</Customers>

<Products>
    <Product>
        <ProductId>PROD1</ProductId>
        <ProductDescription>ProdDesciption1</ProductDescription>
        <ProductCost>100</ProductCost>
        <CustomerWhoUseThisProduct>
            <CustomerNumber>CUSTID01</CustomerNumber>
        </CustomerWhoUseThisProduct>
    </Product> 

    <Product>
        <ProductId>PROD2</ProductId>
        <ProductDescription>ProdDesciption2</ProductDescription>
        <ProductCost>555</ProductCost>
        <CustomerWhoUseThisProduct>
            <CustomerNumber>CUSTID02</CustomerNumber>
        </CustomerWhoUseThisProduct>
    </Product> 

    <Product>
    <ProductId>PROD3</ProductId>
    <ProductDescription>ProdDesciption3</ProductDescription>
    <ProductCost>777</ProductCost>
    <CustomerWhoUseThisProduct>
        <CustomerNumber>CUSTID03</CustomerNumber>
    </CustomerWhoUseThisProduct>
    </Product>

</Products>
</info>

目的是输出一个文本文件。预期输出如下所示。

<CustomerInfo>
CustomerID|CustomerAddress|CustomerName|ProductIDUsed|ProductCost|ProductDescription
CUSTID01|Address1|01Name|PROD01|100|ProdDesciption1
CUSTID01|Address1|01Name|PROD02|555|ProdDesciption2
CUSTID02|Address2|02NAME|PROD01|100|ProdDesciption1
CUSTID03|Address3|03NAME|PROD03|777|ProdDesciption3

<ProductInformation>
ProductID|ProductCost|ProductDescription|CustomerID|CustomerAddress|CustomerName
PROD1|100|ProdDesciption1|CUSTID01|Address1|01NAME
PROD2|555|ProdDesciption2|CUSTID02|Address2|02NAME
PROD3|777|ProdDesciption3|CUSTID03|Address3|03NAME

如果根据预期考虑输出是有序的(即列是有序的)。 看来我正在使用密钥加入两个表,这正是我想要做的。

处理客户时。

客户/客户/ CustomerUsesProduct / ProductUsed / ProductNumber =产品/产品/ ProductId

处理产品时。

产品/产品/ CustomerWhoUseThisProduct / CustomerNumber =客户/客户/ CustomerId

由于每个节点都引用其他节点,如何确保不存在循环自引用,因此应用程序可能会挂起。

提前致谢。

1 个答案:

答案 0 :(得分:0)

编辑:为ProductInformation添加模板

我确实需要更改示例XML文件中的/info/Products/Product/ProductId,以便它们与/info/Customers/Customer/CustomerUsesProduct/ProductUsed/ProductNumber匹配。

更新了输入XML:

<info>
  <Customers>
    <Customer>
      <CustomerName>01NAME</CustomerName>
      <CustomerAddress>Address1</CustomerAddress>   
      <CustomerUsesProduct>
        <ProductUsed>
          <ProductNumber>PROD01</ProductNumber>
          <ProductNumber>PROD02</ProductNumber>        
        </ProductUsed>
      </CustomerUsesProduct>      
      <CustomerId>CUSTID01</CustomerId>      
    </Customer>

    <Customer>
      <CustomerName>02NAME</CustomerName>
      <CustomerAddress>Address2</CustomerAddress>   
      <CustomerUsesProduct>
        <ProductUsed>
          <ProductNumber>PROD01</ProductNumber>
        </ProductUsed>
      </CustomerUsesProduct>      
      <CustomerId>CUSTID02</CustomerId>      
    </Customer>

    <Customer>
      <CustomerName>03NAME</CustomerName>
      <CustomerAddress>Address3</CustomerAddress>   
      <CustomerUsesProduct>
        <ProductUsed>
          <ProductNumber>PROD03</ProductNumber>
        </ProductUsed>
      </CustomerUsesProduct>      
      <CustomerId>CUSTID03</CustomerId>
    </Customer>

  </Customers>

  <Products>
    <Product>
      <ProductId>PROD01</ProductId>
      <ProductDescription>ProdDesciption1</ProductDescription>
      <ProductCost>100</ProductCost>
      <CustomerWhoUseThisProduct>
        <CustomerNumber>CUSTID01</CustomerNumber>
      </CustomerWhoUseThisProduct>
    </Product> 

    <Product>
      <ProductId>PROD02</ProductId>
      <ProductDescription>ProdDesciption2</ProductDescription>
      <ProductCost>555</ProductCost>
      <CustomerWhoUseThisProduct>
        <CustomerNumber>CUSTID02</CustomerNumber>
      </CustomerWhoUseThisProduct>
    </Product> 

    <Product>
      <ProductId>PROD03</ProductId>
      <ProductDescription>ProdDesciption3</ProductDescription>
      <ProductCost>777</ProductCost>
      <CustomerWhoUseThisProduct>
        <CustomerNumber>CUSTID03</CustomerNumber>
      </CustomerWhoUseThisProduct>
    </Product>

  </Products>
</info>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="Customers">
    <xsl:text>&#xA;&lt;CustomerInfo&gt;&#xA;</xsl:text>
    <xsl:text>CustomerID|CustomerAddress|CustomerName|ProductIDUsed|ProductCost|ProductDescription&#xA;</xsl:text>
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="Customer">
    <xsl:variable name="vId" select="CustomerId"/>
    <xsl:variable name="vName" select="CustomerName"/>
    <xsl:variable name="vAddress" select="CustomerAddress"/>
    <xsl:for-each select="CustomerUsesProduct/ProductUsed/ProductNumber">
      <xsl:variable name="vCost" select="/info/Products/Product[ProductId=current()]/ProductCost"/>
      <xsl:variable name="vDesc" select="/info/Products/Product[ProductId=current()]/ProductDescription"/>
      <xsl:value-of select="concat($vId,'|',$vAddress,'|',$vName,'|',.,'|',$vCost,'|',$vDesc,'&#xA;')"/>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="Products">
    <xsl:text>&#xA;&lt;ProductInformation&gt;&#xA;</xsl:text>
    <xsl:text>ProductID|ProductCost|ProductDescription|CustomerID|CustomerAddress|CustomerName&#xA;</xsl:text>
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="Product">
    <xsl:variable name="vId" select="ProductId"/>
    <xsl:variable name="vCost" select="ProductCost"/>
    <xsl:variable name="vDesc" select="ProductDescription"/>
    <xsl:for-each select="CustomerWhoUseThisProduct/CustomerNumber">
      <xsl:variable name="vName" select="/info/Customers/Customer[CustomerId=current()]/CustomerName"/>
      <xsl:variable name="vAddress" select="/info/Customers/Customer[CustomerId=current()]/CustomerAddress"/>      
      <xsl:value-of select="concat($vId,'|',$vCost,'|',$vDesc,'|',.,'|',$vAddress,'|',$vName,'&#xA;')"/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

文字输出:

<CustomerInfo>
CustomerID|CustomerAddress|CustomerName|ProductIDUsed|ProductCost|ProductDescription
CUSTID01|Address1|01NAME|PROD01|100|ProdDesciption1
CUSTID01|Address1|01NAME|PROD02|555|ProdDesciption2
CUSTID02|Address2|02NAME|PROD01|100|ProdDesciption1
CUSTID03|Address3|03NAME|PROD03|777|ProdDesciption3

<ProductInformation>
ProductID|ProductCost|ProductDescription|CustomerID|CustomerAddress|CustomerName
PROD01|100|ProdDesciption1|CUSTID01|Address1|01NAME
PROD02|555|ProdDesciption2|CUSTID02|Address2|02NAME
PROD03|777|ProdDesciption3|CUSTID03|Address3|03NAME