XSLT:如果在变量列表中匹配,则修改属性?

时间:2017-05-16 07:27:48

标签: xml xslt xslt-1.0

我正在尝试编写XSLT代码,只有当开头匹配变量oldRoot中的一个字符串时才会修改bind元素的ref属性。此变量将是动态的,并且在生产环境中将包含不同数量的字符串。我当前的解决方案适用于一个字符串,但当我开始将它采用到变量中的许多字符串时,'otherwise'子句使修改重叠,除非该匹配是针对最后一个字符串。我如何打破这个最终的“xsl:copy-of”-statement,以便只有当变量oldRoot中的所有字符串都不匹配时才适用?我只能访问XSLT 1.0。

简化要求:我希望XSLT编辑bind元素的ref属性,其中开头与“list-variable”oldRoot中的一个字符串匹配。编辑应将字符串'_1'添加到匹配字符串的末尾。

示例输入XML:

<Root>
<field>
    <bind ref="$.First.something.other"/>
</field>
<field>
    <bind ref="$.Second.subcat.name"/>
</field>
<field>
    <bind ref="$.Third.subcat.name"/>
</field>
<field>
    <bind ref="$.First"/>
    <field>
        <bind ref="$.subcat.date"/>
    </field>
</field>
<field>
    <bind ref="$.Third.subcat.date"/>
</field>
</Root>

简化XSL:

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

    <xsl:variable name="oldRoot" >
        <block>$.First</block>
        <block>$.Second</block>
    </xsl:variable> 
    <xsl:variable name="end" select="_1"/>

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

<!--    Rewrite attribute ref to work with new XML.-->
    <xsl:template match="*[local-name()='bind']/@ref">
        <xsl:variable name="attribute" select="."/>
        <xsl:for-each select="$oldRoot/block">
            <xsl:choose>
                <xsl:when test="starts-with(substring-after($attribute,.),'.') or $attribute=.">
                    <xsl:attribute name="ref">
                        <xsl:value-of select="."/>
                        <xsl:value-of select="$end"/>       
                        <xsl:value-of select="substring-after($attribute, .)"/>
                    </xsl:attribute>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="$attribute"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

我需要的结果:

<Root>
<field>
    <bind ref="$.First_1.something.other"/>
</field>
<field>
    <bind ref="$.Second_1.subcat.name"/>
</field>
<field>
    <bind ref="$.Third.subcat.name"/>
</field>
<field>
    <bind ref="$.First_1"/>
    <field>
        <bind ref="$.subcat.date"/>
    </field>
</field>
<field>
    <bind ref="$.Third.subcat.date"/>
</field>
</Root>

1 个答案:

答案 0 :(得分:1)

我建议你这样试试:

XSLT 1.0

class Input extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: '',
      onChangeText: '',
    };
  }

  render() {
    return (
      <View>
        <Text>{this.props.label}</Text>
        <TextInput
          value={this.value}
          onChangeText={email => this.props.onChangeText(email)}
        />
      </View>
    );
  }
}

应用于您的输入示例,结果将是:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="oldRoot" >
    <block>$.First</block>
    <block>$.Second</block>
</xsl:variable> 

<xsl:variable name="end" select="'_1'"/>

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

<xsl:template match="bind/@ref">
    <xsl:variable name="match" select="exsl:node-set($oldRoot)/block[starts-with(current(), .)]"/>
    <xsl:choose>
        <xsl:when test="$match">
            <xsl:attribute name="ref">
                <xsl:value-of select="$match"/>
                <xsl:value-of select="$end"/>
                <xsl:value-of select="substring-after(., $match)"/>
            </xsl:attribute>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

请注意<?xml version="1.0" encoding="UTF-8"?> <Root> <field> <bind ref="$.First_1.something.other"/> </field> <field> <bind ref="$.Second_1.subcat.name"/> </field> <field> <bind ref="$.Third.subcat.name"/> </field> <field> <bind ref="$.First_1"/> <field> <bind ref="$.subcat.date"/> </field> </field> <field> <bind ref="$.Third.subcat.date"/> </field> </Root> 中添加的引号。

与您的问题无关,但您绝不应该使用像<xsl:variable name="end" select="'_1'"/>这样的黑客。如果您的输入使用命名空间,请让您的样式表使用它。