1

我有以下 XML,需要有条件地过滤 UnitOfMeasure 是否有值。如果 ID = 'AcceptanceCriterionValue1' 的第一个 UnitOfMeasure 包含长度大于 0 的字符串,我应该选择该值。否则,我需要选择 ID = 'AcceptanceCriterionValue2' 的 UnitOfMeasure 节点值。换句话说,如果 pH1 存在,抓住它。否则抓取 pH2:

`

<MaterialLots>
  <MaterialLotProperty>
   <ID>AcceptanceCriterionValue1</ID>
   <Value>
    <ValueString>5</ValueString>
    <UnitOfMeasure>pH1</UnitOfMeasure>
   </Value>
  </MaterialLotProperty>
  <MaterialLotProperty>
   <ID>AcceptanceCriterionValue2</ID>
   <Value>
   <ValueString>7</ValueString>
   <UnitOfMeasure>pH2</UnitOfMeasure>
   </Value>
  </MaterialLotProperty>
</MaterialLots>

`
而且我需要执行以下逻辑。当 pH1 存在时,第一个 xsl:when 语句成功,但如果它为空,则 xsl:otherwise 会触发但由于某种原因不返回 pH2:

`

    <xsl:choose>
         <xsl:when test="ns:MaterialLots/ns:MaterialLotProperty/ns:ID='AcceptanceCriterionValue1' and string-length(ns:MaterialLots/ns:MaterialLotProperty/ns:Value/ns:UnitOfMeasure) &gt; 0">
          <xsl:value-of select="ns:MaterialLots/ns:MaterialLotProperty/ns:Value/ns:UnitOfMeasure" />
        </xsl:when>
        <xsl:otherwise>
         <xsl:if test="ns:MaterialLots/ns:MaterialLotProperty/ns:ID='AcceptanceCriterionValue2' and string-length(ns:MaterialLots/ns:MaterialLotProperty/ns:Value/ns:UnitOfMeasure) &gt; 0">
          <xsl:value-of select="ns:MaterialLots/ns:MaterialLotProperty/ns:Value/ns:UnitOfMeasure" />
         </xsl:if>
        </xsl:otherwise>
</xsl:choose>

`

4

3 回答 3

1

我需要执行以下逻辑。当 pH1 存在时,第一个 xsl:when 语句成功,但如果它为空,则 xsl:otherwise 触发但由于某种原因不返回 pH2

通常,当满足$n1条件时选择节点并在其他情况下选择节点的 XPath 表达式是这样的:$cond$n2

$n1[$cond] | $n2[not($cond)]

适用于您的具体情况,我们替换$n1为:

/*/MaterialLotProperty[ID='AcceptanceCriterionValue1']/Value/UnitOfMeasure

$cond与:

text()

并且$n2

/*/MaterialLotProperty[ID='AcceptanceCriterionValue2']/Value/UnitOfMeasure

因此,可以使用单个 XPath 表达式来选择想要的节点

 /*/MaterialLotProperty[ID='AcceptanceCriterionValue1']/Value/UnitOfMeasure[text()]
|
 /*/MaterialLotProperty[ID='AcceptanceCriterionValue2']/Value/UnitOfMeasure
                      [not(/*/MaterialLotProperty[ID='AcceptanceCriterionValue1']
                                                      /Value/UnitOfMeasure[text()])]

在这个简单的转换中使用这个单一的 XPath 表达式

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/">
    <xsl:value-of select=
    "/*/MaterialLotProperty[ID='AcceptanceCriterionValue1']/Value/UnitOfMeasure[text()]
    |
     /*/MaterialLotProperty[ID='AcceptanceCriterionValue2']/Value/UnitOfMeasure
                      [not(/*/MaterialLotProperty[ID='AcceptanceCriterionValue1']
                                                          /Value/UnitOfMeasure[text()])]
    "/>
  </xsl:template>
</xsl:stylesheet>

在提供的 XML 文档上应用转换时:

<MaterialLots>
    <MaterialLotProperty>
        <ID>AcceptanceCriterionValue1</ID>
        <Value>
            <ValueString>5</ValueString>
            <UnitOfMeasure>pH1</UnitOfMeasure>
        </Value>
    </MaterialLotProperty>
    <MaterialLotProperty>
        <ID>AcceptanceCriterionValue2</ID>
        <Value>
            <ValueString>7</ValueString>
            <UnitOfMeasure>pH2</UnitOfMeasure>
        </Value>
    </MaterialLotProperty>
</MaterialLots>

产生了想要的正确结果

pH1

如果在 XML 文档中替换

<UnitOfMeasure>pH1</UnitOfMeasure>

和:

<UnitOfMeasure/>

再次产生正确的结果:

pH2
于 2016-05-05T04:35:05.987 回答
0

您需要遍历每个 MaterialLotProperty。另外,在选择之前先检查 UnitOfMeasure 的长度。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="foo">
<xsl:output method="xml"/>
<xsl:template match="/">
<xml>
    <xsl:for-each select='//ns:MaterialLotProperty'>
        <xsl:if test='string-length(ns:Value/ns:UnitOfMeasure) &gt; 0'>
            <xsl:element name='output'>
                <xsl:choose>
                    <xsl:when test="(ns:ID='AcceptanceCriterionValue1')">
                        <xsl:value-of select='ns:Value/ns:UnitOfMeasure'/>
                    </xsl:when>
                    <xsl:when test="(ns:ID='AcceptanceCriterionValue2')">
                        <xsl:value-of select='ns:Value/ns:UnitOfMeasure'/>
                    </xsl:when>
                </xsl:choose>
            </xsl:element>
        </xsl:if>
    </xsl:for-each>
</xml>

</xsl:template>
</xsl:stylesheet>

第二个 XSL 输出第一个非空白 UnitOfMeasure。

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="foo">
<xsl:output method="xml"/>
<xsl:template match="/">
<xml>
    <xsl:for-each select='//ns:MaterialLotProperty/ns:Value[string-length( ns:UnitOfMeasure ) &gt; 0]/ns:UnitOfMeasure'>
        <xsl:if test='(position() =1)'>
            <xsl:element name='output'>
                <xsl:value-of select='.'/>
            </xsl:element>
        </xsl:if>
    </xsl:for-each>
</xml>

</xsl:template>
</xsl:stylesheet>
于 2016-05-04T17:19:58.820 回答
0

测试你的第一个度量的表达式是这个......

<xsl:when test="string-length(ns:MaterialLots/ns:MaterialLotProperty[ns:ID='AcceptanceCriterionValue1']/ns:Value/ns:UnitOfMeasure) > 0">

但是,使用变量可能会稍微好一些,以避免一些重复。

<xsl:variable name="uom1" select="ns:MaterialLots/ns:MaterialLotProperty[ns:ID='AcceptanceCriterionValue1']/ns:Value/ns:UnitOfMeasure" />
<xsl:choose>
    <xsl:when test="string-length($uom1) > 0">
        <xsl:value-of select="$uom1" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="ns:MaterialLots/ns:MaterialLotProperty[ns:ID='AcceptanceCriterionValue2']/ns:Value/ns:UnitOfMeasure" />
    </xsl:otherwise>
</xsl:choose>

或者,您可以使用xsl:key

<xsl:key name="MLP" match="ns:UnitOfMeasure" use="../../ns:ID" />

然后你可以这样做

<xsl:choose>
    <xsl:when test="string-length(key('MLP', 'AcceptanceCriterionValue1')) > 0">
        <xsl:value-of select="key('MLP', 'AcceptanceCriterionValue1')" />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="key('MLP', 'AcceptanceCriterionValue2')" />
    </xsl:otherwise>
</xsl:choose>
于 2016-05-04T17:06:23.403 回答