2013-01-16 41 views
0

我对XML数据的结构如下改造:XSLT/XPath的更换特定节点

<root> 
     <main1> 
      <page> 
       <text-body> 
        <title>K1</title> 
        <subtitle>Text</subtitle> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
      </page> 
      <page> 
       <text-body> 
        <title>K2</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
      </page> 
      <page> 
       <text-body> 
        <title>K3</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
      </page> 
     </main1> 
     <main2> 
      <text-body> 
       <title>B</title> 
       <subtitle>B</subtitle> 
       <body>B</body> 
      </text-body> 
      <text-body> 
       <title>C</title> 
       <subtitle>C</subtitle> 
       <body>C</body> 
      </text-body> 
      <text-body> 
       <title>D</title> 
       <subtitle>D</subtitle> 
       <body>D</body> 
      </text-body> 
     </main2> 
</root> 

我需要用头衔K1替换MAIN1 /文本主体中的数据,K2,K3与数据在main2/text-body中,但将其他文本主体元素保留在main1中。输出应该是这样的:

<root> 
     <main1> 
      <page> 
       <text-body> 
        <title>B</title> 
        <subtitle>B</subtitle> 
        <body>B</body> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
      </page> 
      <page> 
       <text-body> 
        <title>C</title> 
        <subtitle>C</subtitle> 
        <body>C</body> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
      </page> 
      <page> 
       <text-body> 
        <title>D</title> 
        <subtitle>D</subtitle> 
        <body>D</body> 
       </text-body> 
       <text-body> 
        <title>Text</title> 
        <subtitel>Text</subtitel> 
       </text-body> 
      </page> 
     </main1> 
     <main2> 
      <text-body> 
       <title>B</title> 
       <subtitle>B</subtitle> 
       <body>B</body> 
      </text-body> 
      <text-body> 
       <title>C</title> 
       <subtitle>C</subtitle> 
       <body>C</body> 
      </text-body> 
      <text-body> 
       <title>D</title> 
       <subtitle>D</subtitle> 
       <body>D</body> 
      </text-body> 
     </main2> 
</root> 

我有以下XSL-代码:

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

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

     <xsl:template match="main1/page/text-body"> 
      <xsl:param name="count" select="title/substring(.,2,1)"/> 
      <xsl:if test="title/substring(.,1,1)='K'"> 
       <xsl:copy-of select="/root/main2/text-body[$count]"/> 
      </xsl:if> 
     </xsl:template> 

    </xsl:stylesheet> 

我尽量选择在标题和检查的人数,如果在文本A K 。但它不起作用。而且我不知道如何保留其他文本元素。这里是当前输出:

<main1> 
      <page> 
       <text-body> 
       <title>B</title> 
       <subtitle>B</subtitle> 
       <body>B</body> 
      </text-body><text-body> 
       <title>C</title> 
       <subtitle>C</subtitle> 
       <body>C</body> 
      </text-body><text-body> 
       <title>D</title> 
       <subtitle>D</subtitle> 
       <body>D</body> 
      </text-body> 


      </page> 
      <page> 
       <text-body> 
       <title>B</title> 
       <subtitle>B</subtitle> 
       <body>B</body> 
      </text-body><text-body> 
       <title>C</title> 
       <subtitle>C</subtitle> 
       <body>C</body> 
      </text-body><text-body> 
       <title>D</title> 
       <subtitle>D</subtitle> 
       <body>D</body> 
      </text-body> 

      </page> 
      <page> 
       <text-body> 
       <title>B</title> 
       <subtitle>B</subtitle> 
       <body>B</body> 
      </text-body><text-body> 
       <title>C</title> 
       <subtitle>C</subtitle> 
       <body>C</body> 
      </text-body><text-body> 
       <title>D</title> 
       <subtitle>D</subtitle> 
       <body>D</body> 
      </text-body> 

      </page> 
     </main1> 
     <main2> 
      <text-body> 
       <title>B</title> 
       <subtitle>B</subtitle> 
       <body>B</body> 
      </text-body> 
      <text-body> 
       <title>C</title> 
       <subtitle>C</subtitle> 
       <body>C</body> 
      </text-body> 
      <text-body> 
       <title>D</title> 
       <subtitle>D</subtitle> 
       <body>D</body> 
      </text-body> 
     </main2> 
</root> 

请帮忙!

回答

0

的主要问题是,你的计数参数被设置为一个字符串,但如果你想在使用作为一个索引,它应该是一个数字,所以你需要做到这一点

<xsl:copy-of select="/root/main2/text-body[number($count)]"/> 

而且,你可能不希望使用XSL:如果这里,因为目前的范本,也不会输出text-body元素当if条件为false时。实际上,您应该将测试移动到模板匹配的一部分。

<xsl:template match="main1/page/text-body[title/substring(.,1,1)='K']"> 

下面是完整的XSLT

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

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

    <xsl:template match="main1/page/text-body[title/substring(.,1,1)='K']"> 
     <xsl:param name="count" select="title/substring(.,2,1)"/> 
     <xsl:copy-of select="/root/main2/text-body[number($count)]"/> 
    </xsl:template> 
</xsl:stylesheet> 

这应该出示你的预期输出。

如果你有兴趣在一个不同的方法,你可以选择定义一个XSL:关键来查找MAIN2 /文本体元素

<xsl:key name="main2" 
    match="main2/text-body" 
    use="concat('K', count(preceding-sibling::text-body) + 1)" /> 

这样的话,你可以删除需要通过子使用下面的模板为MAIN1 /页/文本体匹配元素,而不是

<xsl:template match="main1/page/text-body[key('main2', title)]"> 
    <xsl:copy-of select="key('main2', title)"/> 
</xsl:template> 
+0

根据我的经验,像'吨itle/substring(。,2,1)'在XSLT 2.0中运行良好。什么反对这样做? –

+0

你是对的。我愚蠢地使用XSLT1.0处理器来测试我的答案!我已经修改了我的答案,以删除有关错误的子字符串的位。 –

+0

非常感谢! –

0

使用谓词来仅匹配您想要交换的text-body元素。当你正在使用XSLT 2.0,您可以在谓词中使用正则表达式:

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output method="xml"/> 

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

    <xsl:template match="main1/page/text-body[matches(title,'^K\d+$')]"> 
    <xsl:variable name="count" select="xs:integer(title/substring(.,2))"/> 
    <xsl:copy-of select="/root/main2/text-body[$count]"/> 
    </xsl:template> 

</xsl:stylesheet>