【问题标题】:XSLT - Extract values from XML where element names are in external documentXSLT - 从 XML 中提取元素名称在外部文档中的值
【发布时间】:2017-06-19 13:40:30
【问题描述】:

输入数据

有两个 XML 文档:cars.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<Cars>
  <Car Make="Cadillac" Country="U.S.A.">
    <Options>
      <Airbag Price="100" />
      <CruiseControl Price="200" />
      <SeatBelts Price="300" />
    </Options>
  </Car>
  <Car Make="Volvo" Country="Sweden">
    <Options>
      <Airbag Price="50" />
      <SeatBelts Price="75" />
    </Options>
  </Car>
</Cars>

options.xml:

<?xml version="1.0" ?>
<Options>
  <Option><Name>Airbag</Name></Option>
  <Option><Name>CruiseControl</Name></Option>
  <Option><Name>FalconWings</Name></Option>
</Options>

我意识到cars.xml 中的Options 元素应该是这样定义的:

<Option Name="Airbag" Price="100" />

cars.xml 是来自外部源的输入文件。但是我确实可以控制options.xml 文件的格式。

期望的输出

我想创建一个 .csv,其中包含 cars.xml 中的汽车以及 options.xml 中列出的选项的价格。

# Make,Country,Airbag,CruiseControl,FalconWings
Cadillac,U.S.A.,100,200,N/A
Volvo,Sweden,50,N/A,N/A

问题

如何让样式表打印options.xml 中列出的选项,价格为cars.xml(如果汽车没有选项,则为 N/A)?

【问题讨论】:

  • 我建议您使用 key 来执行查找。

标签: xml xslt saxon


【解决方案1】:

我喜欢用xsl:value-of输出一行csv:

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

    <xsl:output method="text"/>

    <xsl:param name="options-url" select="'options.xml'"/>
    <xsl:variable name="options" select="doc($options-url)//Name"/>

    <xsl:template match="/">
        <xsl:value-of select="'Make', 'Country', $options" separator=","/>
        <xsl:text>&#10;</xsl:text>
        <xsl:apply-templates select="Cars/Car"/>
    </xsl:template>

    <xsl:template match="Car">
        <xsl:value-of select="@*, for $o in $options return ((current()/Options/*[name() = $o]/@Price, 'N/A')[1])" separator=","/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

我明白了

Make,Country,Airbag,CruiseControl,FalconWings
Cadillac,U.S.A.,100,200,N/A
Volvo,Sweden,50,N/A,N/A

【讨论】:

  • 看起来很高级。当我尝试这个时,我确实得到了两辆车的三个选项价格,但它们都是N/A
  • @Roger,我已经编辑了答案并添加了我得到的输出。确保该辅助文件的参数设置正确。
  • 文件options.xml 被读取,因为我的标题行是正确的。回家后我会试着理解你的value-of 表达方式。
  • 此解决方案运行良好。我昨天没有工作,因为我没有制作一个精确的副本。感谢您的支持。
【解决方案2】:

我会做类似的事情

<xsl:variable name="options" select="doc('Options.xml')//Name" as="xs:string*"/>

<!-- header line -->
...
<xsl:value-of select="$options" separator="."/>
...

<xsl:for-each select="Cars/Car">
   <xsl:variable name="car" select="."/>
   <!-- detail line -->
   ...
   <xsl:for-each select="$options">
     <xsl:variable name="o" select="$car/Option/*[name()=current()]">
     <xsl:choose>
       <xsl:when test="exists($o)">
         <xsl:value-of select="',(' || name($o) || '=)' || $o/@Price"/>
       </xsl:when>
       <xsl:otherwise>,N/A</xsl:otherwise>
     </xsl:choose>
  </xsl:for-each>
</xsl:for-each>

【讨论】:

  • 可读性强,适合我。在 when 内部,我使用:&lt;xsl:text&gt;,&lt;/xsl:text&gt; &lt;xsl:value-of select="$o/@Price" /&gt; 来获得我想要的输出。
  • 答案有几个错别字:标题行中的分隔符是一个点iso。逗号,变量o 的值应使用/Options/ 设置并使用/&gt; 终止。
  • 我可以编辑你的答案(修正错别字,添加遗漏的代码)吗?
  • @Roger 如果你愿意的话。
【解决方案3】:

根据 Michael 的建议,我最终得到了这个产生所需输出的样式表:

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

   <xsl:output method="text"/>

   <xsl:variable name="options" select="doc('options.xml')//Name" as="xs:string*"/>

   <xsl:template match="/">

      <!-- header line -->
      <xsl:text># Make,Country,</xsl:text>
      <xsl:value-of select="$options" separator=","/>
      <xsl:text>&#xa;</xsl:text> <!-- newline -->

      <xsl:for-each select="Cars/Car">
         <xsl:variable name="car" select="."/>

         <!-- detail line -->
         <xsl:value-of select="@Make"/>
         <xsl:text>,</xsl:text>
         <xsl:value-of select="@Country"/>

         <xsl:for-each select="$options" >
            <xsl:variable name="o" select="$car/Options/*[name()=current()]"/>
            <xsl:choose>
               <xsl:when test="exists($o)">
                  <xsl:text>,</xsl:text>
                  <xsl:value-of select="$o/@Price"/>
               </xsl:when>
               <xsl:otherwise>,N/A</xsl:otherwise>
            </xsl:choose>
         </xsl:for-each>

         <xsl:text>&#xa;</xsl:text> <!-- newline -->
      </xsl:for-each>
   </xsl:template>
</xsl:stylesheet>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    相关资源
    最近更新 更多