使用xslt从xml复制数据时清除过多的元素

时间:2013-12-02 12:49:47

标签: xml xslt

我正在尝试解析文件manager.xml以获得我需要的正确数据结构。 manager.xml的示例:

<?xml version="1.0" encoding="koi8-r"?>
<manager>
        <priv id="pr.screen.access" caption="c.screen.access">
                <priv id="pr.screen.category.documents" caption="c.main.documents">
                        <priv id="pr.screen.category.documents.rcn" caption="c.main.documents.rcn">
                                <priv id="pr.screen.category.documents.rcn.create" caption="c.main.documents.rcn.create"/>
                        </priv>
                </priv>
        </priv>
        <priv id="pr.screen.category.archives" caption="c.main.archives"/>
        <priv id="pr.screen.category.documents.rcn.create_as" caption="c.main.documents.rcn.create_as" parent="pr.screen.access"/>
        <priv id="pr.screen.category.transport_management.documents" caption="c.main.transport_management.documents"/>
        <caption id="c.screen.access">
                <loctext lang="ru" long="access"/>
        </caption>
        <caption id="c.main.documents">
                <loctext lang="ru" long="documents"/>
        </caption>
        <caption id="c.main.documents.rcn">
                <loctext lang="ru" long="rcn"/>
        </caption>
        <caption id="c.main.documents.rcn.create">
                <loctext lang="ru" long="rcn_create"/>
        </caption>
        <caption id="c.main.archives">
                <loctext lang="ru" long="archives"/>
        </caption>
        <caption id="c.main.documents.rcn.create_as">
                <loctext lang="ru" long="rcn_create-as"/>
        </caption>
        <caption id="c.main.transport_management.documents">
                <loctext lang="ru" long="transport_documents"/>
        </caption>
</manager>

基本上我需要使用所有嵌套元素复制所有“priv”元素,并且还要找到具有“parent”属性的“priv”元素,并将其放入相应的“priv”元素,其中“id”属性等于“parent”。 / p>

除此之外,我还需要为每个“priv”元素添加“caption_ru”属性,其值从“loctext”元素的属性“long”获取,该元素位于“caption”元素内,其中“id”属性等于“标题“priv”的属性。这部分是有效的,但是有没有机会通过使用xsl:key函数来解决它?

我有下一个xslt,它几乎按照预期工作,但是我遇到了额外的“priv”元素,这是我在转换后获得的,我找不到任何方法来摆脱它们: XSL:

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

        <xsl:template match="@* | node()">
                <xsl:copy>
                        <xsl:attribute name='caption_ru'>
                                <xsl:value-of select="//manager/caption[@id=current()/@caption]/loctext[@lang='ru']/@long"/>
                        </xsl:attribute>
                        <xsl:apply-templates select="@* | priv[not(@parent)]"/>
                        <xsl:call-template name="nested_priv"/>
                        <!--xsl:copy>
                                <xsl:apply-templates select="//manager/priv[@parent=current()/@id]"/>
                        </xsl:copy-->

                </xsl:copy>
        </xsl:template>

        <xsl:template name="nested_priv">
                <xsl:copy>
                        <!--xsl:attribute name='caption_ru'>
                                <xsl:value-of select="//manager/caption[@id=current()/@caption]/loctext[@lang='ru']/@long"/>
                        </xsl:attribute-->
                                <xsl:apply-templates select="//manager/priv[@parent=current()/@id]"/>
                </xsl:copy>
        </xsl:template>

</xsl:stylesheet>

这是我在转型后获得的:

<?xml version="1.0" encoding="koi8-r"?>
<manager caption_ru="">
  <priv caption_ru="access" id="pr.screen.access" caption="c.screen.access">
    <priv caption_ru="documents" id="pr.screen.category.documents" caption="c.main.documents">
      <priv caption_ru="rcn" id="pr.screen.category.documents.rcn" caption="c.main.documents.rcn">
        <priv caption_ru="rcn_create" id="pr.screen.category.documents.rcn.create" caption="c.main.documents.rcn.create">
          <priv/>
        </priv>
        <priv/>
      </priv>
      <priv/>
    </priv>
    <priv>
      <priv caption_ru="rcn_create-as" id="pr.screen.category.documents.rcn.create_as" caption="c.main.documents.rcn.create_as" parent="pr.screen.access">
        <priv/>
      </priv>
    </priv>
  </priv>
  <priv caption_ru="archives" id="pr.screen.category.archives" caption="c.main.archives">
    <priv/>
  </priv>
  <priv caption_ru="transport_documents" id="pr.screen.category.transport_management.documents" caption="c.main.transport_management.documents">
    <priv/>
  </priv>
  <manager/>
</manager>

2 个答案:

答案 0 :(得分:0)

这样怎么样?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" version="1.0" encoding="koi8-r" indent="yes"/>

<xsl:key name="caption" match="caption" use="@id" />

<xsl:template match="/manager">
<xsl:copy>
    <xsl:apply-templates select="priv"/>
</xsl:copy>
</xsl:template>

<xsl:template match="priv">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="caption_ru">
            <xsl:value-of select="key('caption', @caption)/loctext/@long" />
        </xsl:attribute>
        <xsl:apply-templates select="priv"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="@*">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

已解决上面列出的xsl,这是基于user3016153的回答,我非常感谢。我不确定我是否应该接受他的回答,但我做了,因为它非常有帮助。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="xml" version="1.0" encoding="koi8-r" indent="yes"/>

<xsl:key name="caption" match="caption" use="@id" />
<xsl:key name="child_priv" match="priv" use="@parent"/>

<xsl:template match="/manager">
        <xsl:copy>
            <xsl:apply-templates select="priv[not(@parent)]"/>
        </xsl:copy>
</xsl:template>

<xsl:template match="priv">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="caption_ru">
            <xsl:value-of select="key('caption', @caption)/loctext[@lang='ru']/@long" />
        </xsl:attribute>
        <xsl:apply-templates select="priv"/>
        <xsl:apply-templates select="key('child_priv',current()/@id)"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="@*">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>