简体   繁体   English

XSLT更新属性,仅赋予新值和属性的XPath

[英]XSLT to update an attribute given just the new value and XPath to the attribute

I have some code that compares two XML documents for attribute differences (updates only, not new attribute nodes) and generates a set of XPath pointers to the attributes and the new values for the attribute. 我有一些代码比较两个XML文档的属性差异(仅更新,而不是新的属性节点),并生成一组指向该属性的XPath指针和该属性的新值。

The Setup 设置

For example, given an old XML and new xml: 例如,给定旧的XML和新的xml:

Old XML 旧的XML

<EntityA>
  <EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/>
</EntityA>

New XML 新的XML

<EntityA>
  <EntityB id="foo2" value="bar2"/>
</EntityA>

My code would return 我的代码会返回

/EntityA/EntityB/@id, foo2
/EntityA/EntityB/@value, bar2

I would like to generate an XSLT that merges the old XML into the new XML, to create the following XML: 我想生成一个XSLT,它将旧的XML合并为新的XML,以创建以下XML:

<EntityA>
  <EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/>
</EntityA>

All answers I've found on SO assume some prior knowledge about the attribute name. 我在SO上找到的所有答案都假定具有有关属性名称的一些先验知识。 In this case, I'm given only the XPath reference the attribute, not the name itself. 在这种情况下,我仅给XPath引用赋予属性,而不给名称本身。 I know I could parse the XPath string to derive the attribute name, but would prefer to keep that complexity out of the code. 我知道我可以解析XPath字符串以派生属性名称,但是希望将这种复杂性排除在代码之外。

What I've tried 我尝试过的

I can't use an attribute value template because I need to copy the ignoredbutsave attribute from the old XML. 我无法使用属性值模板,因为我需要从旧的XML中复制ignoredbutsave属性。 I've tried to use an xsl:param to select the attribute name from the XPath and use it within an xsl:attribute, like this: 我尝试使用xsl:param从XPath中选择属性名称,并在xsl:attribute中使用它,如下所示:

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

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

  <xsl:template match="/EntityA/EntityB/@id">
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
       <xsl:param name="newValue" select="name(/EntityA/EntityB/@id)"/>
         <xsl:attribute name="$newValue">newAttributeId</xsl:attribute>
     </xsl:copy>
  </xsl:template>

  <xsl:template match="/EntityA/EntityB/@value">
    <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
       <xsl:param name="myattrname" select="name(/EntityA/EntityB/@value)"/>
         <xsl:attribute name="$myattrname">newAttributeValue</xsl:attribute>
     </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

However, this causes the error The value '$myattrname' of the attribute 'name' is not a valid QName. 但是,这会导致错误The value '$myattrname' of the attribute 'name' is not a valid QName.

So, the question is given an XPath for an attribute and a new value for that attribute, how do I generate an an XSLT that updates that value without explicitly referencing the attribute name? 因此,为问题提供了一个属性的XPath和该属性的新值,我如何生成一个XSLT来更新该值而无需显式引用属性名?

This XSLT transformation: 此XSLT转换:

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

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

  <xsl:template match="/EntityA/EntityB/@id">
    <xsl:attribute name="{name()}">foo2</xsl:attribute>
  </xsl:template>

  <xsl:template match="/EntityA/EntityB/@value">
    <xsl:attribute name="{name()}">bar2</xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

Applied to your old XML: 应用于您的旧XML:

<EntityA>
  <EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/>
</EntityA>

Yields your old XML with the required attribute value substitutions made: 使用所需的属性值替换产生旧的XML:

<EntityA>
  <EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/>
</EntityA>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM