XSL:copy-of如何从节点复制某些属性?

时间:2014-02-18 17:59:02

标签: xml xslt xpath

如何从节点复制某些属性。我想从节点“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?

不同

2 个答案:

答案 0 :(得分:3)

我认为您可以使用此处的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 ,因为条件可以作为select表达式的一部分。

答案 1 :(得分:1)

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

<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>