如何将前缀类型添加到重复父节点并使用 XSLT 选择每个元素的所有元素?

Posted

技术标签:

【中文标题】如何将前缀类型添加到重复父节点并使用 XSLT 选择每个元素的所有元素?【英文标题】:How to add prefixed type into repeating parent node and select all elements for each using XSLT? 【发布时间】:2013-05-01 22:38:55 【问题描述】:

我想知道我们如何将前缀类型 [xsi:type"..."] 添加到每个重复的父节点并选择它的所有子节点。 xml 是肥皂信封,输出是对信封的标题和正文的修改。 示例输入 xml 是:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://Example1.com"
xmlns:ns1="http://Sample1.com">

<soapenv:Header>
    <ns:SessionHeader>
        <ns:Auth>a1b2c4d5</ns:Auth>
    </ns:SessionHeader>
</soapenv:Header>
<soapenv:Body>
    <ns:Create>
        <!--Zero or more repetitions:-->
        <ns:BankAccount>
            <ns1:AccountNumber>1111</ns1:AccountNumber>
            <ns1:BillingState>Texas</ns1:BillingState>
            <ns1:Name>John</ns1:Name>
            <ns1:Phone>+1 111</ns1:Phone>
            <ns1:Site>Chicago</ns1:Site>
            <ns1:Website>www.site1.com</ns1:Website>
            .
            .
        </ns:BankAccount>
      <ns:BankAccount>
            <ns1:AccountNumber>222</ns1:AccountNumber>
            <ns1:BillingState>Hawai</ns1:BillingState>
            <ns1:Name>Bob</ns1:Name>
            <ns1:Phone>+2 222</ns1:Phone>
            <ns1:Site>Canada</ns1:Site>
            <ns1:Website>www.site2.com</ns1:Website>
            .
            .
        </ns:BankAccount>
        .
        .
        . 
    </ns:Create>
</soapenv:Body>
</soapenv:Envelope> 

给定输入 xml 所需的输出 xml 是

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns="http://Example1.com" 
xmlns:ns1="http://Sample1.com" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <soapenv:Header>
        <ns:SessionHeader>
            <ns:Auth>a1b2c4d5</ns:Auth>
        </ns:SessionHeader>
    </soapenv:Header>
    <soapenv:Body>
        <ns:Create>
           <ns:BankAccount xsi:type="Account" xmlns="http://Example1.com" >
            <ns1:AccountNumber>1111</ns1:AccountNumber>
            <ns1:BillingState>Texas</ns1:BillingState>
            <ns1:Name>John</ns1:Name>
            <ns1:Phone>+1 111</ns1:Phone>
            <ns1:Site>Chicago</ns1:Site>
            <ns1:Website>www.site1.com</ns1:Website>
              .
              .
          </ns:BankAccount>

          <ns:BankAccount xsi:type="Account" xmlns="http://Example1.com" >
            <ns1:AccountNumber>222</ns1:AccountNumber>
            <ns1:BillingState>Hawai</ns1:BillingState>
            <ns1:Name>Bob</ns1:Name>
            <ns1:Phone>+2 222</ns1:Phone>
            <ns1:Site>Canada</ns1:Site>
            <ns1:Website>www.site2.com</ns1:Website>
              .
              .
          </ns:BankAccount>

          .
          .
          .

        </ns:Create>
    </soapenv:Body>
</soapenv:Envelope> 

我已尝试使用下面提到的 XSL,但它没有产生所需的结果。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="/">
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:ns="http://Example1.com"
        xmlns:ns1="http://Sample1.com"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <soapenv:Header>
            <ns:SessionHeader>
                <ns:Auth>
                    <xsl:value-of select="//ns:Auth"/>
                </ns:Auth>
            </ns:SessionHeader>
        </soapenv:Header>
        <soapenv:Body>
            <ns:Create>
                <ns:BankAccount xsi:type="Account" xmlns="http://Example1.com">
                  <xsl:apply-template select="node()"/>
                </ns:BankAccount>
            </ns:Create>
        </soapenv:Body>
    </soapenv:Envelope>
</xsl:template>

</xsl:stylesheet>

我不确定我哪里出错了。 我是否需要首先获取所有父“BankAccount”节点及其元素以添加前缀,然后重新构建肥皂信封? 请指导我。

【问题讨论】:

【参考方案1】:

如果您只想将xsi:type="Account" 添加到每个ns:BankAccount 元素,请使用identity transformation 和ns:BankAccount 的专用模板,该模板在添加属性时复制内容:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:ns="http://Example1.com"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

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

    <xsl:template match="ns:BankAccount">
        <xsl:copy>
            <xsl:attribute name="xsi:type">Account</xsl:attribute>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

感谢您的回复和提示。我已经尝试过了,但我得到了这样的答案: w3.org/2001/XMLSchema-instance" type="Account">' 这不是我所期待的......我需要这样 'Example1.com">'

以上是关于如何将前缀类型添加到重复父节点并使用 XSLT 选择每个元素的所有元素?的主要内容,如果未能解决你的问题,请参考以下文章

使用xslt和c#从中选择​​一个xml节点并根据其值添加更多节点[重复]

XSLT 将命名空间前缀添加到元素最佳实践

XSLT 用子节点重复父节点

如何使用 xslt 将父节点命名空间复制到子元素?

XSLT 将具有父节点的节点移动到具有给定属性的每个父节点的兄弟节点中

xsd:any 元素的命名空间前缀并使用 XSLT 添加命名空间前缀