XSLT:到处更改属性值

时间:2017-12-04 13:47:47

标签: xml xslt

我有未知/不同结构的XML文件。我必须更改属性的值  这只是一个例子,结构可以是任何东西:

<root>
    <SomeElement endTime='12:00:00' />
    <subLevel>
        <OtherElement endTime='14:00:00' />
    </subLevel>
</root>

我需要在发生的任何地方更改endTime属性。输出应为

<root>
    <SomeElement endTime='11:59:59' />
    <subLevel>
        <OtherElement endTime='13:59:59' />
    </subLevel>
</root>

如果我知道属性的确切位置,但是如果我不知道XML文件的结构并且需要为文件中的每个元素更改它,我可以这样做吗?这甚至可能吗?

2 个答案:

答案 0 :(得分:2)

好吧,如果您知道如何更改该值,请编写模板

<xsl:template match="@endTime">
  <xsl:attribute name="{name()}">
   <!-- code to alter value here -->
  </xsl:attribute>
</xsl:template>

并使用身份转换处理其余部分,即在带有<xsl:mode on-no-match="shallow-copy"/>的XSLT 3中或在带有

的早期版本中处理
<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

在XSLT 2或3中,您可以直接使用xs:time值和持续时间之间的减法来实现更改:

<xsl:template match="@endTime">
  <xsl:attribute name="{name()}" select="xs:time(.) - xs:dayTimeDuration('PT1S')"/>
</xsl:template>

无需先创建xs:dateTime

http://xsltransform.hikmatu.com/b4GWV4

上的在线示例

答案 1 :(得分:2)

添加到身份转换

仅限XSLT v3.0

<xsl:mode on-no-match="shallow-copy"/>

XSLT v1.0-x.x

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

@endTime的覆盖,它将在一秒之前替换现有值:

  <xsl:param name="datePart">2017-12-04T</xsl:param>
  <xsl:template match="@endTime">
    <xsl:attribute name="endTime">
      <xsl:value-of select="substring-after(xs:dateTime(concat($datePart,.))
                            - xs:dayTimeDuration('PT1S'),$datePart)"/>
    </xsl:attribute>
  </xsl:template>

暂时预先设置日期,以便可以使用内置的dateTime计算功能。

完整XSLT

(日期时间计算需要XSLT 2.0或更高版本)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xsl:output indent="yes"/>
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:param name="datePart">2017-12-04T</xsl:param>
  <xsl:template match="@endTime">
    <xsl:attribute name="endTime">
      <xsl:value-of select="substring-after(xs:dateTime(concat($datePart,.))
                            - xs:dayTimeDuration('PT1S'),$datePart)"/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

应用于您的XML输入:

<root>
    <SomeElement endTime='12:00:00' />
    <subLevel>
        <OtherElement endTime='14:00:00' />
    </subLevel>
</root>

提供您请求的XML输出:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <SomeElement endTime="11:59:59"/>
    <subLevel>
        <OtherElement endTime="13:59:59"/>
    </subLevel>
</root>
根据要求