带有多个条目的XSLT 2.0反向键,来自外部文档

时间:2014-08-25 16:11:22

标签: xslt xpath xslt-2.0

我有这份文件。

<?xml version="1.0" encoding="UTF-8"?>
<file>
    <dummy_content>Contextual content<uicontrol>Mappings</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Code in</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Name</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Code out</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Mapping mode</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Change</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>OK</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Add</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Edit</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Add/Update</uicontrol>More content</dummy_content>
</file>

我有一个文件,其中包含对这些UI控件的引用:

<?xml version="1.0" encoding="UTF-8"?>
<!-- DICT_min.xml -->
<DICTIONARY>
    <DICT_ENTRY DICT_ID="ui58384" DICT_STRING="Reset target"/>
    <DICT_ENTRY DICT_ID="ui16245" DICT_STRING="Mappings"/>
    <DICT_ENTRY DICT_ID="ui56897" DICT_STRING="Mappings"/>
    <DICT_ENTRY DICT_ID="ui56841" DICT_STRING="Code in"/>
    <DICT_ENTRY DICT_ID="ui56850" DICT_STRING="Code in"/>
    <DICT_ENTRY DICT_ID="ui56868" DICT_STRING="Code in"/>
    <DICT_ENTRY DICT_ID="ui56869" DICT_STRING="Code out"/>
    <DICT_ENTRY DICT_ID="ui56919" DICT_STRING="Add/Update"/>
    <DICT_ENTRY DICT_ID="ui56920" DICT_STRING="Add/Update"/>
    <DICT_ENTRY DICT_ID="dml3152" DICT_STRING="Retrieved"/>
    <DICT_ENTRY DICT_ID="dml3261" DICT_STRING="Sent"/>
</DICTIONARY>

理想情况下,我希望将它们组合在一起:以便id属性位于原始文件中。有点棘手,因为每个可能的字符串通常有多个ID。但是,如果我有多个元素,它将帮助用户,因为它们更容易删除错位的元素,而不是键入正确的属性。所以我的目标就是这个。

<?xml version="1.0" encoding="UTF-8"?>
<file>
    <dummy_content>Contextual content
        <uicontrol ref="ui16245">Mappings</uicontrol>
        <uicontrol ref="ui56897">Mappings</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content
        <uicontrol ref="ui56841">Code in</uicontrol>
        <uicontrol ref="ui56850">Code in</uicontrol>
        <uicontrol ref="ui56868">Code in</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Name</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol ref="ui56869">Code out</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Mapping mode</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Change</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>OK</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Add</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content<uicontrol>Edit</uicontrol>More content</dummy_content>
    <dummy_content>Contextual content
        <uicontrol ref="ui56919">Add/Update</uicontrol>
        <uicontrol ref="ui56920">Add/Update</uicontrol>More content</dummy_content>
</file>

我一直在尝试大量的xslt命令。在我的天真和愚蠢中,我所拥有的最新想法是:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="dictstrings" select="document('DICT_min.xml')"/>
<xsl:key name="ui_ids" match="DICT_ENTRY" use="@DICT_STRING"/>

    <!--Identity template, copies all content -->
     <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!--Template for uicontrol that provides custom behavior -->
    <xsl:template match="uicontrol">  
        <xsl:variable name="uistring" select="."/>
            <xsl:apply-templates select="$dictstrings"> 
                <xsl:with-param name="uistring" select="$uistring"/>
            </xsl:apply-templates>  
    </xsl:template>

    <xsl:template match="DICT_ENTRY">
        <xsl:param name="uistring"/>
        <xsl:for-each select="key('ui_ids',$uistring)">
            <xsl:element name="uicontrol">
                <xsl:attribute name="ref">
                    <xsl:value-of select="@DICT_ID"/>
                </xsl:attribute>
                <xsl:value-of select="@DICT_STRING"/>
            </xsl:element>
        </xsl:for-each> 
    </xsl:template>

</xsl:stylesheet>

由于你知识渊博且观察力很强(我不是),因此产生了这个:

<?xml version="1.0" encoding="UTF-8"?>
<file>
    <dummy_content>Contextual content<DICTIONARY/>More content</dummy_content>
    <dummy_content>Contextual content<DICTIONARY/>More content</dummy_content>
...

你知道为什么我的上下文搞砸了,尝试访问外部DICT_min.xml文件吗?如何控制上下文,以便xsl和xpath知道要搜索哪个文件?

你有更好的建议吗?

2 个答案:

答案 0 :(得分:1)

而不是<xsl:apply-templates select="$dictstrings">使用<xsl:apply-templates select="key('ui_ids', ., $dictstrings)">

然后你的模板应该是

<xsl:template match="DICT_ENTRY">
  <uicontrol ref="{@DICT_ID}">
   <xsl:value-of select="@DICT_STRING"/>
  </uicontrol>
</xsl:template>

答案 1 :(得分:1)

以这种方式试试吗?

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:param name="dictstrings" select="document('DICT_min.xml')"/>
<xsl:key name="dict_entry" match="DICT_ENTRY" use="@DICT_STRING"/>

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

<xsl:template match="uicontrol[key('dict_entry', ., $dictstrings)]">  
    <xsl:apply-templates select="key('dict_entry', ., $dictstrings)"/> 
</xsl:template>

<xsl:template match="DICT_ENTRY">  
    <uicontrol ref="{@DICT_ID}">
        <xsl:value-of select="@DICT_STRING"/>
    </uicontrol>
</xsl:template>

</xsl:stylesheet>