【问题标题】:XSL:copy-of How to copy some attributes from a node?XSL:copy-of 如何从节点复制一些属性?
【发布时间】:2014-02-18 17:59:01
【问题描述】:

如何从节点复制一些属性。例如。我只想从节点“Extn”复制“Srno”、“RollNo”、“right”。

<Main>
  <SubMainLevel1 material="12" feature="range">
    <SubMainLevel2 arg1="abc" arg2="123">
      <Item name="hello" desc="one" />
      <Detail long="high" short="wide" />
      <Extn Srno="12" RollNo="12" weight="12" folds="2" right="Y" left="N" top="T" bottom="V" />
    </SubMainLevel2>
    <SubMainLevel2 arg1="cyz" arg2="123">
      <Item name="hello2" desc="two" />
      <Detail long="short" short="wide" />
      <Extn Srno="" RollNo="" weight="" folds="1" right="Y" left="N" top="T" bottom="V" />
    </SubMainLevel2>
  </SubMainLevel1>
</Main>

我使用的Xsl如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:strip-space elements="*" />
   <xsl:template match="/">
      <Job>
         <xsl:copy-of select="Main/SubMainLevel1/@*[name()='material']" />
         <Lines>
            <xsl:for-each select="/Main/SubMainLevel1/SubMainLevel2">
               <xsl:if test="@arg2 = '123'">
                  <Line>
                     <xsl:copy-of select="@*" />
                     <xsl:copy-of select="node()[name() = 'Item']" />
                     <xsl:copy-of select="node()[name() = 'Detail']" />
                     <xsl:copy-of select="node()[name() = 'Extn']" />
                  </Line>
               </xsl:if>
            </xsl:for-each>
         </Lines>
      </Job>
   </xsl:template>
</xsl:stylesheet>

我怎样才能用上面提到的值来限制节点“Extn”。

预期输出是

<?xml version="1.0" encoding="UTF-8"?>
<Job material="12">
   <Lines>
      <Line arg1="abc" arg2="123">
         <Item name="hello" desc="one" />
         <Detail long="high" short="wide" />
         <Extn Srno="12" RollNo="12"  right="Y"/>
      </Line>
      <Line arg1="cyz" arg2="123">
         <Item name="hello2" desc="two" />
         <Detail long="short" short="wide" />
         <Extn Srno="" RollNo=""  right="Y"/>
      </Line>
   </Lines>
</Job>

注意:这与“How not to copy some attributes?”不同

【问题讨论】:

  • 我们能看看输出应该是什么样子吗?
  • 你想把它们复制到哪里是个问题。
  • 为什么是@*[name()='material']?这和@material 有区别吗?

标签: xml xslt xpath


【解决方案1】:

我认为您可以从这里使用identity template 受益

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

这意味着不要写这个......

  <Line>
      <xsl:copy-of select="@*" />
      <xsl:copy-of select="node()[name() = 'Item']" />
      <xsl:copy-of select="node()[name() = 'Detail']" />
      <xsl:copy-of select="node()[name() = 'Extn']" />
  </Line>

你可以这样写

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

那么,当你可以选择你想要的属性时,你只需要一个匹配Extn的模板

<xsl:template match="Extn">
   <xsl:copy>
      <xsl:apply-templates select="@Srno|@RollNo|@right|node()"/>
   </xsl:copy>
</xsl:template>

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:strip-space elements="*" />
   <xsl:output method="xml" indent="yes" />

   <xsl:template match="Main">
      <Job>
         <xsl:copy-of select="SubMainLevel1/@*[name()='material']" />
         <Lines>
            <xsl:apply-templates select="SubMainLevel1/SubMainLevel2[@arg2 = '123']" />
         </Lines>
      </Job>
   </xsl:template>

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

   <xsl:template match="Extn">
      <xsl:copy>
         <xsl:apply-templates select="@Srno|@RollNo|@right|node()"/>
      </xsl:copy>
   </xsl:template>

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

注意我在 SubMainLevel2 上使用模板匹配,而不是 xsl:for-each,还要注意如何不需要 xsl: if 作为条件可以作为选择表达式的一部分。

【讨论】:

    【解决方案2】:

    我相信这会做你想要的(以比你现在更简单的方式):

    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
    
    <xsl:template match="/">
        <Job material="{Main/SubMainLevel1/@material}">
            <Lines>
                <xsl:for-each select="Main/SubMainLevel1/SubMainLevel2[@arg2=123]">
                    <Line>
                        <xsl:copy-of select="@* | Item | Detail" />
                        <Extn Srno="{Extn/@Srno}" RollNo="{Extn/@RollNo}" right="{Extn/@right}" />
                    </Line>
                </xsl:for-each>
            </Lines>
        </Job>
    </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

    • 给出一些错误。如果我只是从您的 xsl 中获取 &lt;Extn Srno="{Extn/@Srno}" RollNo="{Extn/@RollNo}" right="{Extn/@right}" /&gt;,则效果很好
    • 对我来说很好 - 请参见此处:xsltransform.net/948Fn5e您使用的是哪个处理器,您得到的确切错误是什么?
    • @livinggourmand 这对我来说也很好用。确保你给他们一个完整的样式表,而不仅仅是模板。我已经编辑了我的答案以在我的(单个)模板周围包含样式表包装器。
    猜你喜欢
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多