XSLT转换 - 在迭代期间通过一组节点设置变量

时间:2017-12-06 11:16:57

标签: xml xslt

我的任务是创建XSLT转换。 在过程语言中,解决方案看起来像这样:

foreach( Book book in set)
{
   int importanceIndicator = 0;
   foreach( Page page in book )
   {
      if(page.name == "important_page")
      {
         importanceIndicator = 1;
         break;
      }
   }
   book.newField.importanceIndicator = importanceIndicator;
}

如何在XSLT中解决这个问题(与程序语言有很大不同)?

示例XML文件:

输入:

<set>
    <book>
        <page name="important_page"></page>
        <page name="first_page"></page>
        <page name="important_page"></page>
        <page name="second_page"></page>
        <page name="important_page"></page>
    </book>
    <book>
        <page name="another_page"></page>
        <page name="first_page"></page>
        <page name="3_page"></page>
        <page name="second_page"></page>
        <page name="another_page"></page>
    </book>
    <book>
        <page name="important_page"></page>
        <page name="first_page"></page>
        <page name="important_page"></page>
        <page name="second_page"></page>
        <page name="another_page"></page>
    </book>
</set>

输出:

<set>
    <book>
        <newField importance_indicator="1"></newField>
    </book>
    <book>
        <newField importance_indicator="0"></newField>
    </book>
    <book>
        <newField importance_indicator="1"></newField>
    </book>
</set>

3 个答案:

答案 0 :(得分:2)

在XSLT中,您不需要循环来完成此任务。处理book节点时,可以检查其子节点的内容。

<xsl:template match="book">
    <newfield>
         <xsl:choose>
            <xsl:when test="page/@name='important page'">
                <xsl:attribute name="importance_indicator" select="1">
            </xsl:when>
             <xsl:otherwise>
                <xsl:attribute name="importance_indicator" select="0">
            </xsl:otherwise>

答案 1 :(得分:1)

首先从identity template开始(在这种情况下只会复制set节点)

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

然后,在转换book元素时,您需要一个与book匹配的新模板,您可以在其中复制book元素并添加newField元素< / p>

<xsl:template match="book">
    <xsl:copy>
        <newField>
           <!-- Add code for attribute -->
        </newField>
    </xsl:copy>
</xsl:template>

要创建属性,您可以xsl:attribute使用包含条件的xsl:choose进行检查

    <xsl:attribute name="importance_indicator">
        <xsl:choose>
            <xsl:when test="page[@name='important_page']">1</xsl:when>
            <xsl:otherwise>0</xsl:otherwise>
        </xsl:choose>
    </xsl:attribute>

试试这个XSLT

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

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

    <xsl:template match="book">
        <xsl:copy>
            <newField>
                <xsl:attribute name="importance_indicator">
                    <xsl:choose>
                        <xsl:when test="page[@name='important_page']">1</xsl:when>
                        <xsl:otherwise>0</xsl:otherwise>
                    </xsl:choose>
                </xsl:attribute>
            </newField>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

请注意,匹配“book”的模板可以通过使用Attribute Value Templates(由{ }符号表示来简化,这些符号会导致内部表达式被评估,而不是按字面输出)

<xsl:template match="book">
    <xsl:copy>
        <newField importance_indicator="{number(boolean(page[@name='important_page']))}"/>
    </xsl:copy>
</xsl:template>

如果page[@name='important_page'])是“important_page”,page将会选择boolean()<compatible-screens> <!-- all small size screens --> <screen android:screenSize="small" android:screenDensity="ldpi" /> <screen android:screenSize="small" android:screenDensity="mdpi" /> <screen android:screenSize="small" android:screenDensity="hdpi" /> <screen android:screenSize="small" android:screenDensity="xhdpi" /> <screen android:screenSize="small" android:screenDensity="xxhdpi" /> <screen android:screenSize="small" android:screenDensity="xxxhdpi" /> <!-- all normal size screens --> <screen android:screenSize="normal" android:screenDensity="ldpi" /> <screen android:screenSize="normal" android:screenDensity="mdpi" /> <screen android:screenSize="normal" android:screenDensity="hdpi" /> <screen android:screenSize="normal" android:screenDensity="xhdpi" /> <screen android:screenSize="normal" android:screenDensity="xxhdpi" /> <screen android:screenSize="normal" android:screenDensity="xxxhdpi" /> </compatible-screens> 将返回true或false,具体取决于该页面是否存在,然后number将“true”转换为“1”或“false”为“0”。

答案 2 :(得分:0)

我找到了答案,可以这样做:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="/">

    <set>
        <xsl:for-each select="set">
          <xsl:for-each select="book">
            <book>
            <xsl:variable name="importanceIndicatorTmp">
              <xsl:choose>
                <xsl:when test= "page/@name = 'important_page'">1</xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
              </xsl:choose>
            </xsl:variable>
            <newField importanceIndicator="{$importanceIndicatorTmp}"></newField>
            </book>
          </xsl:for-each>
        </xsl:for-each>
    </set>

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