如何在XSLT中删除整个文档中相同属性的子集

时间:2018-04-13 02:29:20

标签: xml xslt

我需要在XSLT处理期间在整个文档中删除属性的子集。在以下XML示例中,我想删除仅包含数字的@id属性。对于@id的其余部分,它们不会更改。

<?xml-stylesheet type="text/xsl" href="recursion2.xsl" ?>

<list>
    <book id="B1">
        <label>1</label>
        <title id="1">A Good Story</title>
        <author>James Soul</author>
    </book>
    <book id="B2">
        <label>2</label>
        <title id="21">The Perfect Storm</title>
        <author>Laura Smith</author>
    </book>
    <journal id="J1">
        <label>3</label>
        <citation id="3">Tom Lane. The smart computation method. 2003;23(5):123-128.</citation>
    </journal>
    <journal id="J2">
        <label>4</label>
        <citation id="122">Luna Shen. The identification of new gene, SMACT4. 2010;10(2):23-38. </citation>
    </journal>
</list>

预期结果应为:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="recursion2.xsl" ?>
<list>
<book id="B1">
    <label>1</label>
    <title>A Good Story</title>
    <author>James Soul</author>
</book>
<book id="B2">
    <label>2</label>
    <title>The Perfect Storm</title>
    <author>Laura Smith</author>
</book>
<journal id="J1">
    <label>3</label>
    <citation>Tom Lane. The smart computation method. 2003;23(5):123-128.</citation>
</journal>
<journal id="J2">
    <label>4</label>
    <citation>Luna Shen. The identification of new gene, SMACT4. 2010;10(2):23-38. </citation>
</journal>
</list>

我尝试了以下代码,并认为test="number(@id)=@id"会选择仅包含数字的@id,但所有@id都已删除。

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

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

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

  <xsl:template>
      <xsl:if test="number(@id)=@id"/>
  </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:2)

您可以尝试使用以下模板,该模板仅在值不是数字时处理@id

<xsl:template match="@id">
    <xsl:if test="not(number(.))">
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:if>
</xsl:template>

完成XSLT

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

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

    <xsl:template match="@id">
        <xsl:if test="not(number(.))">
            <xsl:copy>
                <xsl:apply-templates />
            </xsl:copy>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

输出

<list>
    <book id="B1">
        <label>1</label>
        <title>A Good Story</title>
        <author>James Soul</author>
    </book>
    <book id="B2">
        <label>2</label>
        <title>The Perfect Storm</title>
        <author>Laura Smith</author>
    </book>
    <journal id="J1">
        <label>3</label>
        <citation>Tom Lane. The smart computation method. 2003;23(5):123-128.</citation>
    </journal>
    <journal id="J2">
        <label>4</label>
        <citation>Luna Shen. The identification of new gene, SMACT4. 2010;10(2):23-38. </citation>
    </journal>
</list>

答案 1 :(得分:1)

this post about testing the first character of attributes to be a non-numeric value的提示中,我找到了我想要的解决方案:

<xsl:template match="@id[string(number(substring(.,1,1))) !='NaN']" /> 

此代码将删除以数字值开头的所有@id,这足以满足我的需要。原帖有很多很好的解释。