Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml XSLT-基于映射从模板中选择节点_Xml_Xslt_Xslt 2.0 - Fatal编程技术网

Xml XSLT-基于映射从模板中选择节点

Xml XSLT-基于映射从模板中选择节点,xml,xslt,xslt-2.0,Xml,Xslt,Xslt 2.0,这是我为解释而编写的xml内容示例 <doc> <array> <?Table_type Small?> <table> <data>text</data> </table> </array> <array> <?Table_type Medium?>

这是我为解释而编写的xml内容示例

<doc>
    <array>
        <?Table_type Small?>
        <table>
            <data>text</data>
        </table>
    </array>

    <array>
        <?Table_type Medium?>
        <table>
            <data>text</data>
        </table>
    </array>

    <array>
        <?Table_type Large?>
        <table>
            <data>text</data>
        </table>
    </array>
</doc>
但它不会从映射中读取相应的属性值并将其放置在相应的
节点中

我的预期产出是

<doc>
    <array>
        <?Table_type Small?>
        <table>
            <data size="10">text</data>
        </table>
    </array>

    <array>
        <?Table_type Medium?>
        <table>
            <data size="20">text</data>
        </table>
    </array>

    <array>
        <?Table_type Large?>
        <table>
            <data size="30">text</data>
        </table>
    </array>
</doc>

文本
文本
文本

任何关于如何更改模板以从映射中读取正确值并向
节点添加正确属性的建议?

您已经落入了陷阱,这是XSLT-1.0的一个严重问题

避免这种情况的一种方法是将
转换为XSLT文件中的数据岛。这个数据岛需要一个自己的名称空间,我称之为
var
,它必须使用
exclude result prefixes
指令从结果中明确排除

此外,我使用了两个变量来避免XML和XSLT名称空间之间的名称空间冲突

仅供参考:
document(“”)/xsl:stylesheet
引用当前XSLT文档的XML根节点

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:var="some.var" exclude-result-prefixes="var">
  <xsl:output method="xml" indent="yes" />

  <var:tabletypemapping>
        <map parent='Small' mapto='10'/>
        <map parent='Medium' mapto='20'/>
        <map parent='Large' mapto='30'/>
  </var:tabletypemapping>

  <xsl:template match="data">
    <xsl:variable name="procIns" select="ancestor::array/processing-instruction('Table_type')" />
    <xsl:variable name="mapIns"  select="document('')/xsl:stylesheet/var:tabletypemapping/map[@parent = $procIns]/@mapto" />
    <data size="{$mapIns}">
      <xsl:apply-templates/>
    </data>
  </xsl:template>

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

</xsl:stylesheet>

输出为:

<?xml version="1.0"?>
<doc>
    <array>
        <?Table_type Small?>
        <table>
            <data size="10">text</data>
        </table>
    </array>

    <array>
        <?Table_type Medium?>
        <table>
            <data size="20">text</data>
        </table>
    </array>

    <array>
        <?Table_type Large?>
        <table>
            <data size="30">text</data>
        </table>
    </array>
</doc>

文本
文本
文本

您已经落入了XSLT-1.0的一个严重问题的陷阱

避免这种情况的一种方法是将
转换为XSLT文件中的数据岛。这个数据岛需要一个自己的名称空间,我称之为
var
,它必须使用
exclude result prefixes
指令从结果中明确排除

此外,我使用了两个变量来避免XML和XSLT名称空间之间的名称空间冲突

仅供参考:
document(“”)/xsl:stylesheet
引用当前XSLT文档的XML根节点

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:var="some.var" exclude-result-prefixes="var">
  <xsl:output method="xml" indent="yes" />

  <var:tabletypemapping>
        <map parent='Small' mapto='10'/>
        <map parent='Medium' mapto='20'/>
        <map parent='Large' mapto='30'/>
  </var:tabletypemapping>

  <xsl:template match="data">
    <xsl:variable name="procIns" select="ancestor::array/processing-instruction('Table_type')" />
    <xsl:variable name="mapIns"  select="document('')/xsl:stylesheet/var:tabletypemapping/map[@parent = $procIns]/@mapto" />
    <data size="{$mapIns}">
      <xsl:apply-templates/>
    </data>
  </xsl:template>

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

</xsl:stylesheet>

输出为:

<?xml version="1.0"?>
<doc>
    <array>
        <?Table_type Small?>
        <table>
            <data size="10">text</data>
        </table>
    </array>

    <array>
        <?Table_type Medium?>
        <table>
            <data size="20">text</data>
        </table>
    </array>

    <array>
        <?Table_type Large?>
        <table>
            <data size="30">text</data>
        </table>
    </array>
</doc>

文本
文本
文本

您可能不需要在匹配本身中使用复杂的xpath表达式,尤其是在所有
数据
元素前面都有有效的处理指令的情况下

主要问题是AVT用于计算
size
属性。它正在寻找
映射
元素的祖先,而不是当前的
数据
元素。应该是这个

<data size="{$table.type.mapping/map[@parent=current()/ancestor::array/processing-instruction('Table_type')]/@mapto}">

您可能不需要在匹配本身中使用复杂的xpath表达式,尤其是在所有
数据
元素前面都有有效的处理指令的情况下

主要问题是AVT用于计算
size
属性。它正在寻找
映射
元素的祖先,而不是当前的
数据
元素。应该是这个

<data size="{$table.type.mapping/map[@parent=current()/ancestor::array/processing-instruction('Table_type')]/@mapto}">

通过使用键执行查找,可以非常方便(高效)地执行此操作:

XSLT2.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:variable name="table.type.mapping">
    <map parent='Small' mapto='10'/>
    <map parent='Medium' mapto='20'/>
    <map parent='Large' mapto='30'/>
</xsl:variable>

<xsl:key name="size" match="map" use="@parent" />

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

<xsl:template match="data">
    <data size="{key('size', ancestor::array/processing-instruction('Table_type'), $table.type.mapping)/@mapto}">
        <xsl:apply-templates/>
    </data>
</xsl:template>

</xsl:stylesheet>

通过使用键执行查找,可以非常方便(高效)地执行此操作:

XSLT2.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:variable name="table.type.mapping">
    <map parent='Small' mapto='10'/>
    <map parent='Medium' mapto='20'/>
    <map parent='Large' mapto='30'/>
</xsl:variable>

<xsl:key name="size" match="map" use="@parent" />

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

<xsl:template match="data">
    <data size="{key('size', ancestor::array/processing-instruction('Table_type'), $table.type.mapping)/@mapto}">
        <xsl:apply-templates/>
    </data>
</xsl:template>

</xsl:stylesheet>


这个问题被标记为XSLT 2.0。@michael.hor257k:你当然是对的。在发布我的答案后,我才意识到这一点。这个问题被标记为XSLT 2.0。@michael.hor257k:当然你是对的。我在发布我的答案后才意识到这一点。