首页 > 解决方案 > 试图在同一个 XML 文档中使用 XSLT 和 Key 函数查找相关值

问题描述

大家好,

希望您能帮助我解决以下问题。我对 XML 有一点了解,通过反复试验和阅读 Stack Overflow 上的项目,我设法创建了一个有效的 XSLT。唯一不起作用的是获取项目 ID (AI0567) 旁边的项目描述 ("BlaBla")。所以这个描述必须出现在“ns0:CarrierContent”行的级别上。

这里的问题(?)是描述不是一个孩子,它在同一级别。任何人都知道这是否可能?先感谢您!

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ns0:Message xmlns:ns0="####">
<ns0:Header>
</ns0:Header>
<ns0:Customers>
  <ns0:Customer>
    <ns0:Carriers>
      <ns0:Carrier>
        <ns0:ContentLines>
          <ns0:CarrierContent>
            <ns0:CustomerItemNo>AI0567</ns0:CustomerItemNo>
          </ns0:CarrierContent>
        </ns0:ContentLines>
      </ns0:Carrier>
    </ns0:Carriers>
  <ns0:Items>
    <ns0:Item>
      <ns0:No>AI0567</ns0:No>
        <ns0:Description>BlaBla</ns0:Description>
    </ns0:Item>
  </ns0:Items>
</ns0:Customer>
</ns0:Customers>
</ns0:Message>

XSLT:

<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid=”Excel.Sheet”?>
<xsl:stylesheet version="2.0" 
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ns0="###">
<xsl:template match="/">
  <xsl:processing-instruction name="mso-application">   
  <xsl:text>progid="Excel.Sheet"</xsl:text>  
  </xsl:processing-instruction>
  <Workbook>
    <Worksheet ss:Name="Page1">
      <Table>
        <xsl:call-template name="XMLToXSL" />
      </Table>
    </Worksheet>
  </Workbook>
</xsl:template> 
<xsl:template name="XMLToXSL"> 
<xsl:processing-instruction name="mso-application">   
  <xsl:text>progid="Excel.Sheet"</xsl:text>  
</xsl:processing-instruction>                               
<xsl:key name="DescriptionSearch" match="ns0:Message/ns0:Customers/ns0:Customer/ns0:Items/ns0:Item" use="@ns0:Message/ns0:Customers/ns0:Customer/ns0:Items/ns0:Item/ns0:No" />
<xsl:for-each select="/">
<Row>
  <Cell>
    <Data ss:Type="String">
     <xsl:value-of select="ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:CustomerItemNo" />
   </Data>
  </Cell>
  <Cell>
    <Data ss:Type="String">
      <xsl:value-of select="ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:ExternalCustomerItemNo" />
    </Data>
  </Cell>
  <Cell>
    <Data ss:Type="String">
      <xsl:value-of select="key('DescriptionSearch',@ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:CustomerItemNo)" />
    </Data>
  </Cell>
</Row> 
</xsl:for-each>
</xsl:template>
<xsl:template match="/ns0:Message">
</xsl:template>
</xsl:stylesheet> 

  

标签: xmlxsltkey

解决方案


定义有很多问题xsl:key

  1. xsl:key需要是直接的孩子,xsl:stylesheet而不是在里面xsl:template
  2. “use”值以@which 开头,表示属性,但ns0:message不是属性(如果是,则后面不会有子元素)
  3. “使用”值应该与匹配的内容相关。

这意味着,你xsl:key应该看起来像这样

<xsl:key name="DescriptionSearch" match="ns0:Message/ns0:Customers/ns0:Customer/ns0:Items/ns0:Item" use="ns0:No" />

实际上,在这种情况下,您可以将其简化为此,因为您不需要指定匹配的完整路径(除非其他地方有您不需要匹配的具有不同路径的项目)

<xsl:key name="DescriptionSearch" match="ns0:Item" use="ns0:No" />

至于使用key,你的表达方式需要是这样的(再次注意@as的使用是怎么去掉的)

<xsl:value-of select="key('DescriptionSearch',ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:CustomerItemNo)/ns0:Description" />

所以,你的 XSLT 可能看起来像这样......

<xsl:stylesheet version="2.0" 
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:ns0="####">

<xsl:key name="DescriptionSearch" match="ns0:Item" use="ns0:No" />

<xsl:output method="xml" indent="yes" />

<xsl:template match="/">
  <xsl:processing-instruction name="mso-application">   
  <xsl:text>progid="Excel.Sheet"</xsl:text>  
  </xsl:processing-instruction>
  <Workbook>
    <Worksheet ss:Name="Page1">
      <Table>
        <xsl:call-template name="XMLToXSL" />
      </Table>
    </Worksheet>
  </Workbook>
</xsl:template> 

<xsl:template name="XMLToXSL"> 
<xsl:for-each select="/">
<Row>
  <Cell>
    <Data ss:Type="String">
     <xsl:value-of select="ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:CustomerItemNo" />
   </Data>
  </Cell>
  <Cell>
    <Data ss:Type="String">
      <xsl:value-of select="ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:ExternalCustomerItemNo" />
    </Data>
  </Cell>
  <Cell>
    <Data ss:Type="String">
      <xsl:value-of select="key('DescriptionSearch',ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent/ns0:CustomerItemNo)/ns0:Description" />
    </Data>
  </Cell>
</Row> 
</xsl:for-each>
</xsl:template>
<xsl:template match="/ns0:Message">
</xsl:template>
</xsl:stylesheet> 

但我可能会将最终模板简化为此(因为这允许您的 XML 可能包含多个客户

<xsl:template name="XMLToXSL"> 
<xsl:for-each select="/ns0:Message/ns0:Customers/ns0:Customer/ns0:Carriers/ns0:Carrier/ns0:ContentLines/ns0:CarrierContent">
<Row>
  <Cell>
    <Data ss:Type="String">
     <xsl:value-of select="ns0:CustomerItemNo" />
   </Data>
  </Cell>
  <Cell>
    <Data ss:Type="String">
      <xsl:value-of select="ns0:ExternalCustomerItemNo" />
    </Data>
  </Cell>
  <Cell>
    <Data ss:Type="String">
      <xsl:value-of select="key('DescriptionSearch', ns0:CustomerItemNo)/ns0:Description" />
    </Data>
  </Cell>
</Row> 
</xsl:for-each>
</xsl:template>
<xsl:template match="/ns0:Message">
</xsl:template>

推荐阅读