XSL:如何批量设置空属性?

时间:2015-06-27 21:41:18

标签: xslt

这是一个XML文件,表示项目列表及其优先级,范围为1-3。创建文件时,未设置优先级:

<root>
<section number="1">    
<group number="1.1">
  <item date="today" priority="Undefined"><title>Item1</title></item>
  <item date="today" priority="Undefined"><title>Item2</title></item>
  <item date="yesterday" priority="Undefined"><title>Item3</title></item>
</group>
  <group number="1.2">
    <item date="tomorrow" priority="Undefined"><title>Item4</title></item>
    <item date="today" priority="Undefined"><title>Item5</title></item>
    <item date="yesterday" priority="Undefined"><title>Item5</title></item>
  </group>
</section>
</root>

我稍后会按项目列出优先顺序。他们只是在常规文本文件中找到我,但我可以将它们放入任何必要的格式,包括XML。仅举例说明:

<priorities>
<item1 p="1">
<item2 p="3">
<item3 p="1">
<item4 p="2">
<item5 p="3">
<item6 p="3">
</priorities>

我试图编写一个XSL转换来适当地设置每个项目的优先级属性。

在我看来,它应该像这样工作(我已经有了步骤1):

  1. 使用身份转换
  2. 创建某种数据结构(&#39; Item1&#39;:&#39; 1&#39;,&#39; Item2&#39;:&#39; 3&#39;,...)
  3. 创建一个模板:
    • 匹配ITEM元素
    • 检查TITLE
    • 在数据结构中查找该标题
    • 适当设置优先级(我想我知道如何做这部分)
  4. 或者,我想到了另一种方式:

    1. 使用身份转换(已编写)
    2. 创建3个数据结构:
      • $ P1:=(&#39; Item1&#39;,&#39; Item2&#39;)
      • $ P2:=(&#39; Item4&#39;)
      • $ P3:=(&#39; Item2&#39;,&#39; Item5&#39;,&#39; Item6&#39;)
    3. 创建3个模板,每个模板对应一个优先级。例如,P1模板:
      • 匹配ITEM元素
      • 检查TITLE
      • 检查TITLE是否是$ P1的成员:
        • 如果是,请适当设置优先级
        • 如果没有,不做任何事
    4. 注意:这是一个提炼的例子;我正在尝试创建一个解决方案,该解决方案可以处理XML文件,其中包含大约600个带有非常长字符串的项目元素作为TITLE。

      我一直在谷歌上搜索,并且一直想知道这样的事情是否可能。

      使用氧气16。

3 个答案:

答案 0 :(得分:1)

您的基本逻辑是合理的。这完全取决于你的第二个输入(标题到优先级映射)是什么样的。

假设它本身就是XML,那么你可以将它传递给样式表的>> timeit(interadd, number=5000) 43.69953393936157 并将其用作参考。如果您构建映射文档,如下所示:

<xsl:param>

然后你的XSLT看起来像这样:

<root>
    <title priority="1">Item1</title>
    <!-- etc -->
</root>

许多主机环境允许以某种方式将实际节点列表对象传递给XSLT处理器的参数。或者,您当然可以使用文件<?xml version="1.0" encoding="UTF-8" ?> <xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" encoding="UTF-8" indent="yes" /> <!-- pass in your mapping nodelist from the host environment --> <xsl:param name="priorityByTitle" /> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()" /> </xsl:copy> </xsl:template> <xsl:template match="@priority"> <xsl:copy-of select="$priorityByTitle//title[. = current()/../title]/@priority" /> </xsl:template> </xsl:transform>

document()

答案 1 :(得分:1)

如果您可以将优先级作为XML文档提供,那么我建议使用key从那里查找值 - 特别是如果您可以使用XSLT 2.0,其中跨文档查找是微不足道的。

例如,假设XML文档如:

<强> priorities.xml

<priorities>
    <priority title="Item1">1</priority>
    <priority title="Item2">3</priority>
    <priority title="Item3">1</priority>
    <priority title="Item4">2</priority>
    <priority title="Item5">3</priority>
    <priority title="Item6">3</priority>
</priorities>

以下样式表:

XSLT 2.0

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

<xsl:key name="priority-by-title" match="priority" use="@title" />
<xsl:param name="path-to-priorities" select="'path/to/priorities.xml'"/>

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

<xsl:template match="itemx/@priority">
    <xsl:attribute name="priority">
        <xsl:value-of select="key('priority-by-title', ../title, document($path-to-priorities))" />
    </xsl:attribute>
</xsl:template>

</xsl:stylesheet>

将返回:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <section number="1">
      <group number="1.1">
         <item date="today" priority="1">
            <title>Item1</title>
         </item>
         <item date="today" priority="3">
            <title>Item2</title>
         </item>
         <item date="yesterday" priority="1">
            <title>Item3</title>
         </item>
      </group>
      <group number="1.2">
         <item date="tomorrow" priority="2">
            <title>Item4</title>
         </item>
         <item date="today" priority="3">
            <title>Item5</title>
         </item>
         <item date="yesterday" priority="3">
            <title>Item5</title>
         </item>
      </group>
   </section>
</root>

请注意,XML区分大小写:item1Item1不匹配。

要仅将查找限制为优先级文件中具有匹配条目的项目,您可以使用:

<xsl:template match="item[key('priority-by-title', title, document($path-to-priorities))]/@priority">
    <xsl:attribute name="priority">
        <xsl:value-of select="key('priority-by-title', ../title, document($path-to-priorities))" />
    </xsl:attribute>
</xsl:template>

答案 2 :(得分:0)

要使用优先级文件中第n个项目的优先级替换主要输入中的第n个未定义,请使用

<xsl:template match="@priority[.='Undefined']">
  <xsl:variable name="pos" select="count(../preceding::*[@priority='Undefined']"/>
  <xsl:attribute name="priority" select="(doc('priorities.xml')//priority)[$pos]"/>
</xsl:template>

与合适的身份模板一起使用。

那是O(n ^ 2),如果星期六晚上不是午夜,我肯定会做得更好。