在XSLT中匹配文本值

时间:2015-03-27 21:54:04

标签: c# xslt

我遇到了一个奇怪的问题,让我把头发撕掉了。我正在尝试在样式表中匹配XPath。它在我对匹配值进行硬编码时起作用,但在我尝试从变量中获取时却不行。我在这里做错了什么?

XML输入(显然非常简化):

    <container>
      <items>
        <item>
          <LocationID>LOCATION_4</LocationID>
        </item>
        <item>
          <LocationID>LOCATION_4</LocationID>
        </item>
      </items>
    </container>

XSLT模板($ DistinctLocations和$ dataNode是先前声明的变量,我的前几个打印输出是为了验证它们都在范围内)

    <xsl:template name="LocationTemplate">

      <xsl:for-each select="$DistinctLocations/Location">
        <MY-CURRITEM>
          <val>
            <xsl:copy-of select="." />
          </val>
          <distinct>
            <xsl:copy-of select="$DistinctLocations" />
          </distinct>
          <node>
            <xsl:copy-of select="$dataNode" />
          </node>
          <itemloc>
            <xsl:copy-of select="$dataNode//item[LocationID = 'LOCATION_4'][1]/LocationID" />
          </itemloc>
          <itemlocdot>
            <xsl:copy-of select="$dctNode//risk[LocationID = .][1]/LocationID" />
          </itemlocdot>
          <itemloctext>
            <xsl:copy-of select="$dctNode//risk[LocationID = text()][1]/LocationID" />
          </itemloctext>
          <itemloc2>
            <xsl:copy-of select="$dataNode//item[string(LocationID) = string(.) ][1]/LocationID" />
          </itemloc2>
          <itemloc3>
            <xsl:copy-of select="$dataNode//item[string(LocationID) = string(text()) ][1]/LocationID" />
          </itemloc3>
        </MY-CURRITEM>
      </xsl:for-each>
    </xsl:template>

输出:

<MY-CURRITEM>
  <val>
    <Location>LOCATION_4</Location>
  </val>
  <distinct>
    <DistinctLocations>
      <Location>LOCATION_4</Location>
    </DistinctLocations>
  </distinct>
  <node>
    <container>
      <items>
        <item>
          <LocationID>LOCATION_4</LocationID>
        </item>
        <item>
          <LocationID>LOCATION_4</LocationID>
        </item>
      </items>
    </container>
  </node>
  <itemloc>
    <LocationID>LOCATION_4</LocationID>
  </itemloc>
  <itemlocdot />
  <itemloctext />
  <itemloc2 />
  <itemloc3 />
</MY-CURRITEM>

如您所见,我对该值进行硬编码的节点返回匹配项。我尝试匹配变量值的所有其他函数都无法匹配。由于硬编码有效,我猜测它是类型之间的某种不匹配,但我已经尝试了所有可以想到的类型转换组合,而且我没有得到任何结果。

编辑:人们正在请求整个样式表。这是巨大的,需要一些时间来简化。与此同时,这里是变量的来源:

$ DistinctLocations是从C#传递的参数

args.AddParam("DistinctLocations", string.Empty, xDistinctLocs.CreateNavigator().Select("/"));

<xsl:param name="DistinctLocations" />

$ dataNode是正在转换的原始XML,存储在变量中:

<xsl:variable name="dataNode" select="." />

1 个答案:

答案 0 :(得分:1)

请注意以下简化示例:

<强> XML

<root>
    <locations>
        <location>LOCATION_2</location>
    </locations>
    <items>
        <item>
            <id>1</id>
            <location>LOCATION_1</location>
        </item>
        <item>
            <id>2</id>
            <location>LOCATION_2</location>
        </item>
    </items>
</root>

<强> XSLT

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/root">
    <xsl:copy>
        <xsl:for-each select="locations/location">
            <location>
                <value>
                    <xsl:value-of select="." />
                </value>
                <hard-code>
                    <xsl:copy-of select="//item[location='LOCATION_2']" />
                </hard-code>
                <dot>
                    <xsl:copy-of select="//items/item[location=.]" />
                </dot>
                <current>
                    <xsl:copy-of select="//items/item[location=current()]" />
                </current>
            </location>          
      </xsl:for-each>
    </xsl:copy>     
</xsl:template>

</xsl:stylesheet>

<强>结果

<?xml version="1.0" encoding="utf-8"?>
<root>
   <location>
      <value>LOCATION_2</value>
      <hard-code>
         <item>
            <id>2</id>
            <location>LOCATION_2</location>
         </item>
      </hard-code>
      <dot/>
      <current>
         <item>
            <id>2</id>
            <location>LOCATION_2</location>
         </item>
      </current>
   </location>
</root>

为什么结果的<dot>元素为空?因为在表达式中:

"//items/item[location=.]" 

内部点表示外部item节点 - 而不是当前location节点。表达式正在查找item,其值等于其location子项的值。当然,不存在这样的项目。

这就是为什么XSLT添加了current() function,它在谓词中使用时不会改变上下文。