简体   繁体   English

子节点的XSLT转换

[英]XSLT transformation of child nodes

I'm using boost serialization for persistence, and since the library doesn't have support for the idea of saving to an older version of the archive/data structure, I though I'd give XSLT & XPath a shot at transforming from a new version to an older version as needed. 我正在使用boost序列化来实现持久性,并且由于该库不支持保存到较旧版本的归档/数据结构的想法,因此尽管我会给XSLT和XPath一个尝试从新版本转换的想法根据需要将其版本升级到旧版本。

I've gotten about half way there, but can't seem to finish it up ( this is also my first venture into XSLT & XPath/XQuery, so please forgive any obvious mistakes ). 我已经走了一半,但似乎还没完成(这也是我第一次涉足XSLT&XPath / XQuery,所以请原谅任何明显的错误)。

Here's my starting XML: 这是我的起始XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="7">
<tester class_id="0" tracking_level="0" version="0">
    <count>2</count>
    <item_version>0</item_version>
    <item class_id="2" class_name="CLASS_D" tracking_level="0" version="0">
        <A class_id="1" tracking_level="1" version="0" object_id="_0">
            <pimpl class_id="3" tracking_level="1" version="0" object_id="_1">
                <b>1</b>
            </pimpl>
        </A>
        <pimpl class_id="4" tracking_level="1" version="0" object_id="_2">
            <c>2</c>
        </pimpl>
    </item>
    <item class_id="5" class_name="CLASS_E" tracking_level="0" version="0">
        <A object_id="_3">
            <pimpl class_id_reference="3" object_id="_4">
                <b>1</b>
            </pimpl>
        </A>
        <pimpl class_id="6" tracking_level="1" version="0" object_id="_5">
            <f>2</f>
        </pimpl>
    </item>
</tester>
</boost_serialization>

What I want to do, is transform the item with the attribute class_name="CLASS_E" to be like the item with class_name="CLASS_D" but I need to leave the object_id attribute alone. 我想做的是将属性为class_name =“ CLASS_E”的项转换为类似于具有class_name =“ CLASS_D”的项,但我需要单独保留object_id属性。

This is what I want: 这就是我要的:

<?xml version="1.0" encoding="utf-8"?>
<boost_serialization signature="serialization::archive" version="7">
  <tester class_id="0" tracking_level="0" version="0">
    <count>2</count>
    <item_version>0</item_version>
    <item class_id="2" class_name="CLASS_D" tracking_level="0" version="0">
      <A class_id="1" tracking_level="1" version="0" object_id="_0">
        <pimpl class_id="3" tracking_level="1" version="0" object_id="_1">
          <b>1</b>
        </pimpl>
      </A>
      <pimpl class_id="4" tracking_level="1" version="0" object_id="_2">
        <c>2</c>
      </pimpl>
    </item>
    <item class_name="CLASS_D" class_id="2" tracking_level="0" version="0">
      <A object_id="_3">
        <pimpl class_id_reference="3" object_id="_4">
          <b>1</b>
        </pimpl>
      </A>
      <pimpl class_id="4" tracking_level="1" version="0" object_id="_5">
        <c>2</c>
      </pimpl>
    </item>
  </tester>
</boost_serialization>

This is the template as I have so far: 到目前为止,这是模板:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" encoding="UTF-8" indent="yes"/>

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

  <!-- replace attribute class_name value with another-->
  <!-- replace attribute class_id value with another-->
  <!-- only on this node!-->
  <!-- could call another template to change more nested things-->
  <xsl:template match="item/@class_name[. =  'CLASS_E']">
    <xsl:attribute name="class_name">CLASS_D</xsl:attribute>
    <xsl:attribute name="class_id">2</xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

I'm not sure how to continue editing the child node of the item I've matched with this line: as I need to change the "f" node to "c" and change the pimpl "class_id" from 6 to 4 我不确定如何继续编辑与此行匹配的项目的子节点:因为我需要将“ f”节点更改为“ c”,并将pimpl“ class_id”从6更改为4

Thanks in advance 提前致谢

The item you have just matched is an attribute, and so has no child nodes! 您刚刚匹配的项目是一个属性,因此没有子节点! The parent node will have been matched by the identity template, and so to 'continue' editing, just have a template matching the class_id attribute you wish to match, but include a match on the relevant item in the xpath expression. 父节点将通过身份模板进行匹配,因此要进行“继续”编辑,只需有一个模板,该模板与您希望匹配的class_id属性匹配,但在xpath表达式中的相关上包括一个匹配

For example, to change the class_id of the pimpl element, add this template 例如,要改变PIMPL元素的类标识码 ,添加该模板

 <xsl:template match="item[@class_name =  'CLASS_E']/pimpl/@class_id">
    <xsl:attribute name="class_id">4</xsl:attribute>
 </xsl:template>

And to change the f element, add this template 并更改f元素,添加此模板

<xsl:template match="item[@class_name =  'CLASS_E']/pimpl/f">
   <c>
      <xsl:apply-templates select="@*|node()"/>
   </c>
</xsl:template>

Remember, the match applies to the input document, so it doesn't matter that in the output document you have changed 'CLASS_E' to 'CLASS_D'. 请记住,匹配项适用于输入文档,因此在输出文档中将“ CLASS_E”更改为“ CLASS_D”都没关系。

Note that you may have an issue with your current template that matches the class_name attribute. 请注意,您当前的模板可能与class_name属性匹配存在问题。 In this you are replacing it with two attributes, including the class_id attribute which already exists. 在此,您将其替换为两个属性,包括已经存在的class_id属性。 XSLT will replace attribute in the output tree where one with the same name has already been output. XSLT将替换输出树中的属性,在该树中已经输出了相同名称的属性。 This means if your XML actually looked like this... 这意味着如果您的XML实际上看起来像这样...

<item class_name="CLASS_E" class_id="5"  tracking_level="0" version="0">

Then it would be output would actually look this this 然后它将被输出,实际上看起来像这样

<item class_name="CLASS_D" class_id="5" tracking_level="0" version="0">

This is because the identity template will match the class_id attribute after your template that matches the class_name and so will replace the class_id attribute which the one it has currently matched. 这是因为身份模板将在与class_name匹配的模板之后与class_id属性匹配,因此将替换其当前已匹配的class_id属性。

But to cut a long story short, try this XSLT..... 但总而言之,请尝试使用此XSLT .....

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

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

  <xsl:template match="item/@class_name[. =  'CLASS_E']">
    <xsl:attribute name="class_name">CLASS_D</xsl:attribute>
  </xsl:template>

  <xsl:template match="item[@class_name =  'CLASS_E']/@class_id">
    <xsl:attribute name="class_id">2</xsl:attribute>
  </xsl:template>

  <xsl:template match="item[@class_name =  'CLASS_E']/pimpl/@class_id">
     <xsl:attribute name="class_id">4</xsl:attribute>
  </xsl:template>

  <xsl:template match="item[@class_name =  'CLASS_E']/pimpl/f">
     <c>
        <xsl:apply-templates select="@*|node()"/>
     </c>
  </xsl:template>
</xsl:stylesheet>

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

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