【问题标题】:Modifying a substring of an attribute in a node and all children修改节点和所有子节点中属性的子字符串
【发布时间】:2014-09-18 16:06:57
【问题描述】:

我已经进行了大量搜索,但还没有完全能够使用 XSLT 找到任何东西。我正在尝试采用 XML 模板(用于 McPAT,部分如下所示)指示系统规范并复制 component id="system.core0" name="core0" 节点,以便我可以拥有 N 个核心节点。每个都必须有“system.core#”作为 id 和“core#”作为名称,# 是核心编号,0-n。

我还必须在任何后代节点中复制它,例如下面的 system.core0.itlb 节点。

更进一步,在具有诸如“config.system.cpu.clock”之类的值的任何后代节点中,我必须将节点编号附加到“cpu”。

最后,我必须覆盖 param name="number_of_cores" value="1" 在系统下 param name="number_of_cores" value="n" 和改变 param name="homogenous_cores" value="1"param name="homogenous_cores" value="0"

XML 当前如下所示:

<?xml version="1.0" ?>
<component id="root" name="root">
    <component id="system" name="system">
         <param name="number_of_cores" value="1"/>
         <param name="homogeneous_cores" value="1"/>
         <param name="number_of_L1Directories" value="0"/>
         <param name="number_of_L2Directories" value="0"/>
         <param name="number_of_L2s" value="1"/> 
         <param name="Private_L2" value="0"/>
         <param name="number_of_L3s" value="0"/> 
         <param name="number_of_NoCs" value="1"/>
         ...
         <component id="system.core0" name="core0">
             <!-- Core property -->
             <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
             <param name="opt_local" value="1"/>      
             <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

             ...
             <component id="system.core0.itlb" name="itlb">
                 <param name="number_entries" value="{config.system.cpu.itb.size}"/>
                 <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
                 ...
             </component>
         </component>
     </component>
 </component>

这里有好几行。感谢 SO,我已经复制了 system.core0 节点 N 次。我会发布链接,但我找不到页面。我确实知道 Dimitre Novatchev 给出了我所遵循的答案,我想感谢他在这方面的帮助。到目前为止,XSLT 样式表如下所示:

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

    <xsl:param name="n" select="5"/>

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

    <xsl:template match="component[@id='system']/component[@name='core0']">
        <xsl:call-template name="copyNtimes">
            <xsl:with-param name="n" select="$n"/>
            <xsl:with-param name="core_num" select="1"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="copyNtimes">
        <xsl:param name="n" select="0"/>
        <xsl:param name="core_num" select="1"/>

        <xsl:if test="$n > 0">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
            <xsl:text>
            </xsl:text>
            <xsl:call-template name="copyNtimes">
                <xsl:with-param name="n" select="$n -1"/>
                <xsl:with-param name="core_num" select="$core_num+1"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

因此,在通过 xsltproc 运行此程序结束时,我将带有 system.core0 的原始文件复制了 N 次。剩下的东西让我发疯了好几天。如何更改我创建的每个新节点的核心编号,并在所有子节点中也反映这一点?任何帮助都会有所帮助,即使它不是代码。我玩过制作新模板和使用副本,但似乎没有什么能让我更接近。

我还可以将这一切都带入另一种语言,例如 Perl,在那里我可以运行 XSLT 样式表来复制更改并手动修改属性字符串,如果这样更容易的话。我知道 Perl 有一些非常好的用于 XML 和 XSLT 的模块。不过,我觉得 XSLT 应该能够做到这一点,而且由于我是新手,所以这种格式让我失望。

编辑: 我需要的一个示例输出是这样的:

<?xml version="1.0" ?>
    <component id="root" name="root">
        <component id="system" name="system">
             <param name="number_of_cores" value="3"/>
             <param name="homogeneous_cores" value="0"/>
             <param name="number_of_L1Directories" value="0"/>
             <param name="number_of_L2Directories" value="0"/>
             <param name="number_of_L2s" value="1"/> 
             <param name="Private_L2" value="0"/>
             <param name="number_of_L3s" value="0"/> 
             <param name="number_of_NoCs" value="1"/>
             <!--...-->
             <component id="system.core0" name="core0">
                 <!-- Core property -->
                 <param name="clock_rate" value="{1e-6/config.system.cpu0.clock*1e12}"/>
                 <param name="opt_local" value="1"/>      
                 <stat name="total_instructions" value="{stats.system.cpu0.iq.iqInstsIssued}"/>
                 <!--...-->
                 <component id="system.core0.itlb" name="itlb">
                     <param name="number_entries" value="{config.system.cpu0.itb.size}"/>
                     <stat name="total_accesses" value="{stats.system.cpu0.itb.fetch_accesses}"/>
                     ...
                 </component>
             </component>
             <component id="system.core1" name="core1">
                 <!-- Core property -->
                 <param name="clock_rate" value="{1e-6/config.system.cpu1.clock*1e12}"/>
                 <param name="opt_local" value="1"/>      
                 <stat name="total_instructions" value="{stats.system.cpu1.iq.iqInstsIssued}"/>
                 <!--...-->
                 <component id="system.core1.itlb" name="itlb">
                     <param name="number_entries" value="{config.system.cpu1.itb.size}"/>
                     <stat name="total_accesses" value="{stats.system.cpu1.itb.fetch_accesses}"/>
                     ...
                 </component>
             </component><component id="system.core2" name="core2">
                 <!-- Core property -->
                 <param name="clock_rate" value="{1e-6/config.system.cpu2.clock*1e12}"/>
                 <param name="opt_local" value="1"/>      
                 <stat name="total_instructions" value="{stats.system.cpu2.iq.iqInstsIssued}"/>
                 <!--...-->
                 <component id="system.core2.itlb" name="itlb">
                     <param name="number_entries" value="{config.system.cpu2.itb.size}"/>
                     <stat name="total_accesses" value="{stats.system.cpu2.itb.fetch_accesses}"/>
                     ...
                 </component>
             </component>
         </component>
     </component>

【问题讨论】:

  • n 应该从哪里进入新的param name="number_of_cores" value="n"?总是来自 XSLT 中名为 n 的全局参数?
  • 在 XSLT 样式表中,我将它作为参数传递,设置在文件的顶部。我假设我可以在那里使用它,但如果这是不可能的,我相信我可以在顶部发表评论,它必须在不同的地方进行修改以更改 n。
  • 这似乎是一个合法的问题,但很难理解散文。请显示一个实际的 XML 输出并解释它与您的需要有何不同。
  • @kjhughes 实际上刚刚发布了一个答案,该答案解决了我遇到的一个问题并包含了它的输出。但是,除此之外,您会看到 core0 被多次复制。对于每个后续的 code0 节点,我想将其更改为 core1、core2 等。我还需要将其反映在它的所有后代中,因为它们的 id 也将是 system.core0.*。
  • 我刚刚更新了我想要实现的示例输出

标签: xml xslt


【解决方案1】:

(1)如果将以下两个模板添加到 XSLT,

  <xsl:template match="param[@name='number_of_cores' and @value='1']">
    <param name="number_of_cores" value="{$n}"/>
  </xsl:template>

  <xsl:template match="param[@name='homogeneous_cores' and @value='1']">
    <param name="homogenous_cores" value="0"/>
  </xsl:template>

您将覆盖身份转换并能够输出不同的param 元素,如上图所示。

(2)如果在copyNtimes内调整复制如下,

  <xsl:copy>
    <xsl:attribute name="id" select="concat('system.core', $n)"/>
    <xsl:attribute name="name" select="concat('core', $n)"/>
    <xsl:apply-templates select="node()"/>
  </xsl:copy>

您将生成的不是抄送副本,而是@id@name 反映传递给copyNtimes 的副本号的副本。

(3)如果进一步将copyNtimes中的xsl:apply-template调整为隧道n(需要XSLT 2.0),

  <xsl:apply-templates select="node()">
    <xsl:with-param name="compNum" tunnel="yes" select="$n"/>
  </xsl:apply-templates>

并且还要添加一个模板来处理隧道另一边的itlbcomponents

  <xsl:template match="component[@name='itlb']">
    <xsl:param name="compNum" tunnel="yes"/>
    <component name="itlb" value="{concat('system.core',$compNum,'.itlb')}">
      <xsl:apply-templates/>
    </component>
  </xsl:template>

您可以将组件编号添加到后代itlb components

更新(第三次)完整代码和示例输入/输出 XML 文档如下...

此输入 XML 文档:

<?xml version="1.0" ?>
<component id="root" name="root">
  <component id="system" name="system">
    <param name="number_of_cores" value="1"/>
    <param name="homogeneous_cores" value="1"/>
    <param name="number_of_L1Directories" value="0"/>
    <param name="number_of_L2Directories" value="0"/>
    <param name="number_of_L2s" value="1"/> 
    <param name="Private_L2" value="0"/>
    <param name="number_of_L3s" value="0"/> 
    <param name="number_of_NoCs" value="1"/>
    <!-- ... -->
    <component id="system.core0" name="core0">
      <!-- Core property -->
      <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
      <param name="opt_local" value="1"/>      
      <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

      <!-- ... -->
      <component id="system.core0.itlb" name="itlb">
        <param name="number_entries" value="{config.system.cpu.itb.size}"/>
        <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
        <!-- ... -->
      </component>
    </component>
  </component>
</component>

鉴于此 XSLT 转换:

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

  <xsl:param name="n" select="5"/>

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

  <xsl:template match="param[@name='number_of_cores' and @value='1']">
    <param name="number_of_cores" value="{$n}"/>
  </xsl:template>

  <xsl:template match="param[@name='homogeneous_cores' and @value='1']">
    <param name="homogenous_cores" value="0"/>
  </xsl:template>

  <xsl:template match="component[@name='itlb']">
    <xsl:param name="compNum" tunnel="yes"/>
    <component name="itlb" value="{concat('system.core',$compNum,'.itlb')}">
      <xsl:apply-templates/>
    </component>
  </xsl:template>

  <xsl:template match="component[@id='system']/component[@name='core0']">
    <xsl:call-template name="copyNtimes">
      <xsl:with-param name="n" select="$n"/>
      <xsl:with-param name="core_num" select="1"/>
    </xsl:call-template>
  </xsl:template>

  <xsl:template name="copyNtimes">
    <xsl:param name="n" select="0"/>
    <xsl:param name="core_num" select="1"/>

    <xsl:if test="$n > 0">
      <xsl:copy>
        <xsl:attribute name="id" select="concat('system.core', $n)"/>
        <xsl:attribute name="name" select="concat('core', $n)"/>
        <xsl:apply-templates select="node()">
          <xsl:with-param name="compNum" tunnel="yes" select="$n"/>
        </xsl:apply-templates>
      </xsl:copy>
      <xsl:text>
      </xsl:text>
      <xsl:call-template name="copyNtimes">
        <xsl:with-param name="n" select="$n -1"/>
        <xsl:with-param name="core_num" select="$core_num+1"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

将生成此输出 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<component id="root" name="root">
  <component id="system" name="system">
      <param name="number_of_cores" value="5"/>
      <param name="homogenous_cores" value="0"/>
      <param name="number_of_L1Directories" value="0"/>
      <param name="number_of_L2Directories" value="0"/>
      <param name="number_of_L2s" value="1"/> 
      <param name="Private_L2" value="0"/>
      <param name="number_of_L3s" value="0"/> 
      <param name="number_of_NoCs" value="1"/>
      <!-- ... -->
      <component id="system.core5" name="core5">
      <!-- Core property -->
         <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
         <param name="opt_local" value="1"/>      
         <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

         <!-- ... -->
         <component name="itlb" value="system.core5.itlb">
            <param name="number_entries" value="{config.system.cpu.itb.size}"/>
            <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
            <!-- ... -->
         </component>
      </component>
      <component id="system.core4" name="core4">
      <!-- Core property -->
         <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
         <param name="opt_local" value="1"/>      
         <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

         <!-- ... -->
         <component name="itlb" value="system.core4.itlb">
            <param name="number_entries" value="{config.system.cpu.itb.size}"/>
            <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
            <!-- ... -->
         </component>
      </component>
      <component id="system.core3" name="core3">
      <!-- Core property -->
         <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
         <param name="opt_local" value="1"/>      
         <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

         <!-- ... -->
         <component name="itlb" value="system.core3.itlb">
            <param name="number_entries" value="{config.system.cpu.itb.size}"/>
            <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
            <!-- ... -->
         </component>
      </component>
      <component id="system.core2" name="core2">
      <!-- Core property -->
         <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
         <param name="opt_local" value="1"/>      
         <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

         <!-- ... -->
         <component name="itlb" value="system.core2.itlb">
            <param name="number_entries" value="{config.system.cpu.itb.size}"/>
            <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
            <!-- ... -->
         </component>
      </component>
      <component id="system.core1" name="core1">
      <!-- Core property -->
         <param name="clock_rate" value="{1e-6/config.system.cpu.clock*1e12}"/>
         <param name="opt_local" value="1"/>      
         <stat name="total_instructions" value="{stats.system.cpu.iq.iqInstsIssued}"/>

         <!-- ... -->
         <component name="itlb" value="system.core1.itlb">
            <param name="number_entries" value="{config.system.cpu.itb.size}"/>
            <stat name="total_accesses" value="{stats.system.cpu.itb.fetch_accesses}"/>
            <!-- ... -->
         </component>
      </component>

  </component>
</component>

【讨论】:

  • 这实际上正是我解决该问题所需要的!对于每个单独的核心实例,我还需要将 core0 更改为 core0、core1、core2、...、core(n-1)。
  • 答案已更新。你在这里得到一个价格的两个答案。 ;-)
  • 谢谢!这绝对是非常有帮助的!有没有办法,按照同样的思路,将相同的逻辑应用于后代节点,例如,在“system.core4”下,会有一个组件“system.core4.itlb”而不是“system.core0” .itlb"
  • 答案再次更新。由于这已经远远超出了一个 SO 问题,这将是我的最后一次更新。我希望我已经向你展示了足够多的东西,你可以从这里接管。
  • 是的,这绝对是我需要的。你帮了很多忙!谢谢!
猜你喜欢
  • 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
相关资源
最近更新 更多