XSLT 2.0中的XML到XML内部节点结构转换

时间:2018-01-24 17:33:57

标签: xml xslt

我一直试图解决这个问题。

我有一个xml文件:

<ParentNode>
 <RequirementGroup>
    <ID>id1</ID>
    <Requirement>
        <ID>id2</ID>
        <Description>value1</Description>
    </Requirement>
    <RequirementGroup pi="attribute">
        <ID>id3</ID>
        <Requirement>
            <ID>id4</ID>
            <Description>value2</Description>
        </Requirement>
        <Requirement>
            <ID>id5</ID>
            <Description>value3</Description>
        </Requirement>
        <Requirement>
            <ID>id6</ID>
            <Description>value4</Description>
        </Requirement>
        <Requirement>
            <ID>id7</ID>
            <Description>value5</Description>
        </Requirement>
        <RequirementGroup>
            <ID>id8</ID>
            <Requirement>
                <ID>id9</ID>
                <Description>value6</Description>
            </Requirement>
            <RequirementGroup pi="attribute">
                <ID>id10</ID>
                <Requirement>
                    <ID>id11</ID>
                    <Description>value7</Description>
                </Requirement>
            </RequirementGroup>
        </RequirementGroup>
    </RequirementGroup>
 </RequirementGroup>
</ParentNode>

这是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:template name="ExampleTemplate1">
    <ID>Something</ID>
    <Description>example</Description>
    <TypeCode>QUESTION</TypeCode>
    <ValueDataTypeCode>INDICATOR</ValueDataTypeCode>
</xsl:template>
<xsl:template name="ExampleTemplate2">
    <ID>Something</ID>
    <PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
    <xsl:if test="Requirement">
        <xsl:for-each select="Requirement">
            <Example>
                <xsl:call-template name="ExampleTemplate1"/>
            </Example>
        </xsl:for-each>
    </xsl:if>
</xsl:template>
<xsl:template match="ParentNode/RequirementGroup">
    <xsl:if test="RequirementGroup[@pi]">
        <Node1>
            <xsl:call-template name="ExampleTemplate2"/>
            <xsl:if test="RequirementGroup[@pi]">
                <Node1>
                    <xsl:call-template name="ExampleTemplate2"/>
                    <xsl:if test="RequirementGroup[@pi]">
                        <Node1>
                            <xsl:call-template name="ExampleTemplate2"/>
                        </Node1>
                    </xsl:if>
                </Node1>
            </xsl:if>
        </Node1>
    </xsl:if>
</xsl:template>

所以,我想在不同的节点名称中转换XML并使用相同的值(但现在我跳过了值部分,我只想拥有正确的节点结构)。

以下是此转换的输出结果:

<?xml version="1.0" encoding="UTF-8"?>
<Node1>
<ID>Something</ID>
<PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
<Example>
    <ID>Something</ID>
    <Description>example</Description>
    <TypeCode>Something</TypeCode>
    <ValueDataTypeCode>Something</ValueDataTypeCode>
</Example>
<Node1>
    <ID>Something</ID>
    <PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
    <Example>
        <ID>Something</ID>
        <Description>example</Description>
        <TypeCode>Something</TypeCode>
        <ValueDataTypeCode>Something</ValueDataTypeCode>
    </Example>
    <Node1>
        <ID>Something</ID>
        <PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
        <Example>
            <ID>Something</ID>
            <Description>example</Description>
            <TypeCode>Something</TypeCode>
            <ValueDataTypeCode>Something</ValueDataTypeCode>
        </Example>
    </Node1>
  </Node1>
</Node1>

正如您在XML文件中看到的,我为某些节点设置了多个节点组。这就是为什么,我创建了一个带有循环的模板,即使它是一个或五个,也可以获得所有这些模板。但结果不是我想要的那个。

EDITED

所需的输出是:

<?xml version="1.0" encoding="UTF-8"?>
<ParentNode xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <Node1>
    <ID>Something</ID>
    <PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
    <Example>
        <ID>Something</ID>
        <Description>example</Description>
        <TypeCode>Something</TypeCode>
        <ValueDataTypeCode>Something</ValueDataTypeCode>
    </Example>
    <Node1>
        <ID>Something</ID>
        <PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
        <Example>
            <ID>Something</ID>
            <Description>example</Description>
            <TypeCode>Something</TypeCode>
            <ValueDataTypeCode>Something</ValueDataTypeCode>
        </Example>
        <Example>
            <ID>Something</ID>
            <Description>example</Description>
            <TypeCode>Something</TypeCode>
            <ValueDataTypeCode>Something</ValueDataTypeCode>
        </Example>
        <Example>
            <ID>Something</ID>
            <Description>example</Description>
            <TypeCode>Something</TypeCode>
            <ValueDataTypeCode>Something</ValueDataTypeCode>
        </Example>
        <Example>
            <ID>Something</ID>
            <Description>example</Description>
            <TypeCode>Something</TypeCode>
            <ValueDataTypeCode>Something</ValueDataTypeCode>
        </Example>
        <Node1>
            <ID>Something</ID>
            <PropertyGroupTypeCode>Something</PropertyGroupTypeCode>
            <Example>
                <ID>Something</ID>
                <Description>example</Description>
                <TypeCode>Something</TypeCode>
                <ValueDataTypeCode>Something</ValueDataTypeCode>
            </Example>
        </Node1>
    </Node1>
  </Node1>
</ParentNode>

我共享的代码已经可执行,并且已经过简化。

另外,如果有更好的方法,我想听听。因为当我以这种方式进行转换时,我不知道如何替换节点内的值。

EDIT2:

例如,XML1和XML2具有不同的名称空间,用于表达其SchemaID,版本等.XML1:

<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" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:espd="urn:com:grow:espd:02.00.00" xmlns:cac="urn:X-test:UBL:Pre-
award:CommonAggregate" 
xmlns:ccv="urn:isa:names:specification:ubl:schema:xsd:CCV-
CommonAggregateComponents-1" xmlns:cbc="urn:X-test:UBL:Pre-
award:CommonBasic" xmlns:espd-
req="urn:grow:names:specification:ubl:schema:xsd:ESPDRequest-1" 
xmlns:util="java:java.util.UUID">

XML2:

xmlns="urn:X-test:UBL:Pre-award:QualificationApplicationRequest" 
xmlns:cac="urn:X-test:UBL:Pre-award:CommonAggregate" xmlns:cbc="urn:X-
test:UBL:Pre-award:CommonBasic" xmlns:espd="urn:com:grow:espd:02.00.00" 
xmlns:fn="http://www.w3.org/2005/xpath-functions" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:util="java:java.util.UUID" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

XML1的示例节点:

 <cbc:ID schemeID="CriteriaID" schemeAgencyID="EU-COM-GROW" schemeVersionID="1.0">

XML2示例:

<cbc:ID schemeID="CriteriaTaxonomy" schemeAgencyID="EU-COM-GROW" schemeVersionID="02.00.00">

但是,当我将名称空间从XML2复制到我的(你建议的XSLT)文件时,(因为这样我认为它会自动重新创建新的,就像在XML2中一样,并且不会出现问题,转换将是好的)。但它有点奇怪的样子,

输出是:

<cbc:ID xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:ccv-cbc="urn:isa:names:specification:ubl:schema:xsd:CCV-CommonBasicComponents-1" xmlns:cev="urn:isa:names:specification:ubl:schema:xsd:CEV-CommonAggregateComponents-1" xmlns:cev-cbc="urn:isa:names:specification:ubl:schema:xsd:CEV-CommonBasicComponents-1" xmlns:espd="urn:grow:names:specification:ubl:schema:xsd:ESPDResponse-1" xmlns:espd-cac="urn:grow:names:specification:ubl:schema:xsd:ESPD-CommonAggregateComponents-1" xmlns:espd-cbc="urn:grow:names:specification:ubl:schema:xsd:ESPD-CommonBasicComponents-1" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" schemeID="CriteriaID" schemeAgencyID="EU-COM-GROW" schemeVersionID="1.0">

在输出中,它添加了节点旁边的所有命名空间。为什么?如何将所需的命名空间版本等从一个转换为另一个?就像在XML2中更改节点的attirbutes一样。

1 个答案:

答案 0 :(得分:1)

我无法完全明白你想要什么,但从目前为止我所掌握的,你需要一个身份模板,这是

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

以及匹配RequirementGroupRequirement个节点的模板:

<xsl:template match="RequirementGroup">
    <Node1>
        <xsl:apply-templates/>
    </Node1>
</xsl:template>

<xsl:template match="Requirement">
    <Example>
        <xsl:apply-templates/>
    </Example>
</xsl:template>

xsl:apply-templates本身是递归的。整个样式表如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

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

    <xsl:template match="RequirementGroup">
        <Node1>
            <xsl:apply-templates/>
        </Node1>
    </xsl:template>

    <xsl:template match="Requirement">
        <Example>
            <xsl:apply-templates/>
        </Example>
    </xsl:template>

   <xsl:template match="ParentNode">
       <ParentNode>
           <xsl:apply-templates/>
       </ParentNode>
   </xsl:template>

</xsl:stylesheet>

只需添加其他模板即可更改值。