【问题标题】:XSLT:Can I update value in xml node using xslt?XSLT:我可以使用 xslt 更新 xml 节点中的值吗?
【发布时间】:2011-03-18 11:02:55
【问题描述】:

例如我有一个类似的xml

 <books>
   <book id="1">
     <title id="11" name="Basic XML"/>
     <price id="12" amount="500"/>
     <quantity id="13" number="10"/>
   </book>
 </books>

可以将“Basic XML”一书的名称更新为“Basic XSLT”或使用 XSLT 更改任何节点的任何其他属性吗?如果是的话,谁能给我一些例子来说明如何做到这一点?

提前致谢。

【问题讨论】:

  • XSLT 用于将 XML 文件转换为不同的格式 - 听起来你想要的有点过头了。
  • 好问题,+1。请参阅我的答案,以获得基于最基本 XSLT 设计模式的完整、简短和简单的解决方案——身份规则/模板的使用和覆盖。还提供了广泛的解释。
  • @sprenna:正如@Dimitre 的回答所显示的那样……但我同意@Oded:对于值替换,我会选择带有XPath 的节点并使用正确的DOM 方法。
  • @Alejandro: EEEEEEEWWWWWW 。 . .
  • @Dimitre:最佳方法实际上取决于“更新”的含义。如果这意味着从命令行“获取 XML 并序列化其他 XML 文档”,我会选择 XSLT。但是,如果这更像是那些数据库问题或 javascript DOM 或任何嵌入式环境,您或 XSLT 处理器必须调用解析器,执行“更新”然后序列化,我会选择 XPath 选择和 DOM 更新。当然,比值替换更复杂的过程肯定需要 XSLT 或 XQuery。

标签: xml xslt


【解决方案1】:

这种转变

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

 <my:reps>
  <repAttr name="name" value="Basic XSLT"/>
  <repAttr name="amount" value="300"/>
  <repAttr name="number" value="20"/>
 </my:reps>

 <xsl:strip-space elements="*"/>

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

 <xsl:template match=
   "@*[name()=document('')/*/my:reps/*/@name]">

   <xsl:attribute name="{name()}">
    <xsl:value-of select=
    "document('')/*/my:reps/*[@name=name(current())]/@value"/>
   </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<books>
    <book id="1">
        <title id="11" name="Basic XML"/>
        <price id="12" amount="500"/>
        <quantity id="13" number="10"/>
    </book>
</books>

产生想要的正确结果:

<books>
   <book id="1">
      <title id="11" name="Basic XSLT"/>
      <price id="12" amount="300"/>
      <quantity id="13" number="20"/>
   </book>
</books>

解释

  1. 身份规则/模板“按原样”复制每个节点。

  2. 标识模板被单个模板覆盖,该模板匹配任何属性,其名称可以作为repAttr 元素的name 属性之一的值找到,该属性在my:reps 元素中指定(参数嵌入到 XSLT 样式表中)。

  3. 在这种情况下,使用相同名称和新值重新创建(不复制)属性,在相应的repAttr 元素(其value 属性)中指定。

【讨论】:

  • Dimitre 一如既往的好答案
【解决方案2】:

我无法“更新”输入 Xml,因为 XSLT 纯粹是一种输出驱动技术。它会创建一个新文档,并且不能修改现有文档。

您可以制作一个几乎相同的副本,但正如@Oded 评论指出的那样,XSLT 可能是矫枉过正。 xsl 看起来像(修改后的身份转换)

<xsl:stylesheet version="1.0">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
   <xsl:template match="title/@Name">
     <!-- insert logic here to change the value as appropriate -->
   </xsl:template>
</xsl:stylesheet>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多